MySQL 连接没有笛卡尔积的表

MySQL join tables without cartesian product

我有这样的数据集

group_id a_id b_id c_id d_id
1 1
1 2
1 3
1 4
1 5
2 11
2 12
2 13

每条记录仅包含 1 个 *_id,每个 group_id。我需要为每个 group_id.

聚合数据集

结果:

group_id a_id b_id c_id d_id
1 1 2 3 4
1 5
2 11 12 13

一些 *_id 可能为空(group_id 的第 3 行)。 并且避免笛卡尔积很重要(在我的示例中,第 2 行仅包含 d_id = 5,因为前 4 行聚合为一行,并且不再有非聚合的 a_idb_idc_idgroup_id=1).

是否可以通过 MySQL 连接来做到这一点?

WITH 
cte_a AS ( SELECT group_id, a_id, ROW_NUMBER() OVER (PARTITION BY group_id) rn
           FROM test
           WHERE a_id IS NOT NULL ),
cte_b AS ( SELECT group_id, b_id, ROW_NUMBER() OVER (PARTITION BY group_id) rn
           FROM test
           WHERE b_id IS NOT NULL ),
cte_c AS ( SELECT group_id, c_id, ROW_NUMBER() OVER (PARTITION BY group_id) rn
           FROM test
           WHERE c_id IS NOT NULL ),
cte_d AS ( SELECT group_id, d_id, ROW_NUMBER() OVER (PARTITION BY group_id) rn
           FROM test
           WHERE d_id IS NOT NULL ),
cte_n AS ( SELECT group_id, rn FROM cte_a
           UNION
           SELECT group_id, rn FROM cte_b
           UNION
           SELECT group_id, rn FROM cte_c
           UNION
           SELECT group_id, rn FROM cte_d )
SELECT group_id,
       cte_a.a_id,
       cte_b.b_id,
       cte_c.c_id,
       cte_d.d_id
FROM cte_n
LEFT JOIN cte_a USING (group_id, rn)
LEFT JOIN cte_b USING (group_id, rn)
LEFT JOIN cte_c USING (group_id, rn)
LEFT JOIN cte_d USING (group_id, rn)
ORDER BY group_id, rn;

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=87281205ad06780b71b0e90355751e88

PS。如果来自 *_id 的多个值连续不为 NULL,那么这些值可能会出现在不同的输出行中。