MySQL 按除一列以外的所有列分组

标签 mysql sql

我正在寻找一种(更清洁的?)方法来执行以下操作:

假设我有一个表,主表,有大约 15 列,看起来像这样,每个 id 一行:

main:
id      start           end             col4    ...     col15
666     2014-01-01      2014-06-30      ...     ...     ...
1234    2015-03-05      2015-05-02      ...     ...     ...
9876    2014-09-01      2015-01-01      ...     ...     ...
...(etc)

Then I have another table, events, which may have 0, 1, or many rows per id:

events:
id      date            code
666     2014-01-20      "code_a"
1234    2015-05-01      "code_b"
666     2014-01-25      "code_c"
666     2014-02-09      "code_z"
... (etc)

and finally I have a table, codes, which has one row per code, giving a description for the code as well as a type (0,1, or 2):

codes:
code            desc            type
"code_a"        "something"     0 
"code_b"        "somethn else"  1
"code_c"        "another thing" 0
"code_d"        "one more"      2
(no code z)

and what I want as a result is main's 15 columns plus three additional columns which contain comma separated lists of event codes which happened between the start and end dates for that id by type (first column is type 0, second type 1, third type 2), so:

id      start           end             ...     col15   type_0          type_1  type_2
666     2014-01-01      2014-06-30      ...     ...     "code_a,code_c"         
1234    2015-03-05      2015-05-02      ...     ...                     "code_b"
...(etc)

my solution is

select m.*
     , group_concat(c0.code) as type_0
     , group_concat(c1.code) as type_1
     , group_concat(c2.code) as type_2
from main m 
     left join events e on m.id = e.id and e.date between m.start and m.end
     left join codes c0 on c0.code = e.code and c0.type = 0
     left join codes c1 on c1.code = e.code and c1.type = 1
     left join codes c2 on c2.code = e.code and c2.type = 2
group by m.id
       , m.start
       , m.end
       , m.col4
       , m.col5
       , m.col6
       , m.col7
       , m.col8
       , m.col9
       , m.col10
       , m.col11
       , m.col12
       , m.col13
       , m.col14
       , m.col15  

但对我来说,这看起来很讨厌。有没有更优雅的方式来做到这一点(特别是避免 group by 中列出的 15 列)?

最佳答案

在 MySQL 中,您可以只使用 GROUP BY m.id。除非您启用 ONLY_FULL_GROUP_BY 选项,否则它允许您使用不在 GROUP BY 子句中的非聚合列。如果您选择的列不是由分组列唯一标识的列,这可能会产生不可预测的结果,但这里不是这种情况——您正在按 m 表的唯一 ID 的列进行分组,并且所有非聚合列都来自同一个表。

在严格的 SQL 中,您必须通过在子查询中执行 GROUP_CONCAT 来完成此操作,然后将其与 main 表连接。

SELECT *
FROM (SELECT m.id,
            , group_concat(c0.code) as type_0
            , group_concat(c1.code) as type_1
            , group_concat(c2.code) as type_2
     FROM main m
     left join events e on m.id = e.id and e.date between m.start and m.end
     left join codes c0 on c0.code = e.code and c0.type = 0
     left join codes c1 on c1.code = e.code and c1.type = 1
     left join codes c2 on c2.code = e.code and c2.type = 2
     GROUP BY m.id
) t1
JOIN main m ON t1.id = m.id

关于MySQL 按除一列以外的所有列分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31125192/

相关文章:

php - 永久链接不适用于 MySQL 数据库

sql - 查找两个 SQL 数据表之间的不匹配

sql - DB2 CASE 语句

sql - 查找具有相同值的行 PostgreSQL

SQL IsNumeric 不起作用

php - 将mysql单元格转换为文本文件,允许用户下载,然后删除文本文件

Mysql IN子句全表扫描

php - 满足以下要求的 PHP/MySQL 查询应该是什么?

mysql - 获取受帖子类别限制的自定义字段值列表

sql - DB2 EBCDIC 值函数