我有一个 PHP/MySQL 应用程序,它连接到一个数据库,该数据库具有 2 个名为 'displays'
的表和 'display_substances'
.这些表的结构如下:
mysql> DESCRIBE displays;
+----------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------------------+------+-----+---------+----------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| label | varchar(255) | NO | | NULL | |
+----------+----------------------+------+-----+---------+----------------+
mysql> DESCRIBE display_substances;
+--------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------------+------+-----+---------+----------------+
| id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| display_id | smallint(5) unsigned | NO | MUL | NULL | |
| substance_id | mediumint(8) unsigned | NO | MUL | NULL | |
| value | text | NO | | NULL | |
+--------------+-----------------------+------+-----+---------+----------------+
还有一个'substances'
表和外键 display_substances.substance_id
与 substances.id
有关.
'displays'
表正好包含 400 行和 'display_substances'
大约 150 万行。
我想做的是输出所有 400 'displays.label'
放入 HTML 表格中,然后在第二列中显示 'display_substances.value'
.由于该页面一次仅显示 1 种物质,因此还需要基于 'display_substances.substance_id'
.
我遇到的问题是记录只存在于 'display_substances'
中当我们有适当的可用数据时'displays'
.但是,输出必须显示来自 'displays'
的所有 记录然后在 'display_substances'
中没有相应记录的任何内容旁边放置文本“未列出” .
我已经完成了以下操作 - 这给了我想要的输出 - 但有缺陷(请参阅下面的“问题”部分)。
选择“显示”表中的所有记录:
SELECT label FROM displays ORDER BY label ASC
全选
display_substances.display_id
对于当前显示的物质:SELECT display_id FROM display_substances WHERE substance_id = 1
(假设 1 是当前物质 ID)。将 ID 存储在名为$display_substances
的数组中遍历 (1) 并使用
in_array()
查看 (2) 是否存在:foreach ($displays as $display) { // step (1) $display_substances = // See step (2) if (in_array($display['id'], $display_substances)) { // step (3) $display_value = // See step (4) } else { $display_value = 'Not listed'; } $output[] = ['display_label' => $display['label'], 'display_value' => $display_value]; // See step (5) }
如果
in_array()
条件为真,然后我进行查询以选择“display_substances”的相应行:SELECT value FROM display_substances WHERE display_id = $display['id'] AND substance_id = 1
$output
变量缓冲所有数据,然后将其输出到 HTML 表中。我得到的输出正是我想要的。
问题
虽然输出是正确的,但我想将这一切作为 1 个查询(如果可能的话)来完成,因为我需要添加功能以通过 displays.label
进行搜索。或 display_substances.value
- 或两者的结合。第一部分相当简单,因为我可以将 (1) 中的查询修改为:
SELECT label FROM displays WHERE label LIKE '% Foo %' ORDER BY label ASC
但是,这不会生成display_substances.value
可搜索,因为当我们到达步骤 (3) 时,我们正在处理单行 display_substances
不是整张 table 。我看不出如何以不同的方式编写它,因为我们需要知道该表中存在哪些记录用于加载的物质。
我还编写了以下查询 - 但这个不会起作用,因为它遗漏了任何“未列出”的内容:
SELECT displays.label, display_substances.`value` FROM displays JOIN display_substances ON displays.id = display_substances.display_id WHERE display_substances.substance_id = 1
我已阅读 How do I get the records from the left side of a join that do not exist in the joined table?但这没有帮助。
进一步说明
假设 display_substances
中有 120 行对应于物质 ID 1 ( WHERE display_substances.substance_id = 1
)。 查询的输出应始终为 400 行。在这个例子中,120 应该有 display_substances.value
在它们旁边,280 应该有文本“未列出”。
最佳答案
您需要一个左联接和一个 group_concat 来获取左表中的所有记录以及分组依据。
但请记住 group_concat 有一个限制,因此您可能无法获得所有关联的记录,因为它通常用于小字段,但由于您的值有一个“文本”字段,因此您很可能会达到限制
无论如何这是查询
SELECT d.*, GROUP_CONCAT(ds.value) `substances`
FROM displays `d`
LEFT JOIN display_substances `ds` ON `d`.`id` = `ds`.`display_id`
GROUP BY `d`.`id`
如果我理解正确的话,这样的事情可能会奏效
SELECT d.*, IFNULL((SELECT GROUP_CONCAT(value) FROM display_substances `ds` WHERE `ds`.`display_id` = `d`.`id` GROUP BY `ds`.`display_id`), 'Not Listed') `substances`
FROM displays `d`
您可以更新位置并添加 AND substance_id = 1
关于php - 即使记录不存在于另一个表中,也显示 JOIN 查询中的 MySQL 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52933192/