mysql - MySQL - 如何在嵌套的 IFNULL...GROUP_CONCAT() 条件下选择多个列?
问题描述
我有一个连接到 MySQL (5.5.64-MariaDB) 数据库的 Web 应用程序。
查询之一如下:
SELECT
d.id,
d.label AS display_label,
d.anchor,
r.id AS regulation_id,
IFNULL(
(SELECT GROUP_CONCAT(value) FROM display_substances `ds`
WHERE `ds`.`display_id` = `d`.`id`
AND ds.substance_id = 1 -- For example, substance ID = 1
GROUP BY `ds`.`display_id`
), "Not Listed"
) `display_value` FROM displays `d`
JOIN groups g ON d.group_id = g.id
JOIN regulations r ON g.regulation_id = r.id
输出示例如下:
+-----+------------------------------------+------------------------------------------------------------------------------------------+
| id | name | display_value |
+-----+------------------------------------+------------------------------------------------------------------------------------------+
| 4 | techfunction | Intermediate / monomer; Corrosion inhibitor / anodiser / galvaniser; Catalyst; Additive |
| 323 | russia_chemsafety_register_display | Not Listed |
| 733 | peru_pcb_display | Not Listed |
+-----+------------------------------------+------------------------------------------------------------------------------------------+
这个查询可以满足我们的需要。出于解释目的:
- 有2张桌子,
displays
和display_substances
- 查询正在
display_substances.value
为每个displays.id
- 如果没有对应
display_substances.value
的,则返回字符串“未列出”(请参阅上面的查询)。如果有对应的值则display_substances.value
返回。所以在上面的示例数据中,ID323
和733
指的是没有对应条目的场景,因此我们想要“未列出”。相反,ID4
确实有一个值(“中间体/单体;缓蚀剂/阳极氧化剂/镀锌剂;催化剂;添加剂”)所以我们得到了。
表结构如下:
DESCRIBE displays;
+----------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------------------+------+-----+---------+----------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(127) | NO | | NULL | |
| label | varchar(255) | NO | | NULL | |
+----------+----------------------+------+-----+---------+----------------+
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 | |
| automated | tinyint(4) | YES | | NULL | |
+--------------+-----------------------+------+-----+---------+----------------+
我希望能够display_substances.automated
从我的查询中返回(参考上面的表结构)作为列。但我看不出如何做到这一点。
display_substances
对表的引用是ds
,所以我不能在初始SELECT
语句中使用它,因为那时没有别名。同样,没有任何JOIN
条件可以使它成为可能,因为并非返回的每一行都从中获取数据display_substances
(即那些“未列出”的行没有从该表中获取任何内容)。
如果我想display_value
在上面的示例输出旁边显示一个附加列display_substances.automated
,或者NULL
如果它不存在,我该如何实现?
作为参考,该automated
字段包含 1(表示我们的应用程序通过自动化流程获得的数据),或者NULL
如果它不是自动化的。
解决方案
没有 JOIN 条件可以使其成为可能,因为并非返回的每一行都从 display_substances 获取数据
对于这种情况,您可以使用LEFT JOIN
:
SELECT d.id, d.label display_label, d.anchor, r.id regulation_id,
COALESCE(ds.value, 'Not Listed') display_value,
ds.automated
FROM displays d
INNER JOIN groups g ON d.group_id = g.id
INNER JOIN regulations r ON g.regulation_id = r.id
LEFT JOIN (
SELECT display_id, GROUP_CONCAT(value) value, MAX(automated) automated
FROM display_substances
WHERE substance_id = 1
GROUP BY display_id
) ds ON ds.display_id = d.id
我用作MAX(automated)
返回的列,但您可以GROUP_CONCAT(automated)
像使用 for value
and一样使用COALESCE()
:
COALESCE(ds.automated, 'Not Listed')
推荐阅读
- javascript - 谷歌日历 - 事件日期,而不是一审日期
- javascript - 如何在 Chrome 移动设备的大表中加快 ContentEditable td 输入速度
- java - Spring Boot 是否支持服务器名称指示(SNI)?
- for-loop - 数据透视表和 FOR 子句
- python - Elasticsearch:查找一个字段与另一个字段的重叠
- typescript - Typescript 创建描述类型类型的属性,该类型基于抽象类型
- heroku - Autodesk Forge Heroku 部署
- android - React Native Fetch API 仅适用于开发环境
- json - 对于非 CRUD 操作,适当的 Restful API 动词应该是什么?
- python - Python将内联图像添加到多部分/替代电子邮件