mysql - 如何在 MySQL SELECT 中按“行集”分组?
问题描述
我有t
包含列组合的表a
,并且b
已id
分配。这些组合在a
重复b
。对于每个这样的组合,我想确定所有id
s。例子:
+------+------+------+
| id | a | b |
+------+------+------+
| 1 | A | x |
| 1 | B | y |
| 1 | C | z |
| 2 | A | u |
| 2 | B | v |
| 3 | A | x |
| 3 | B | y |
| 3 | C | z |
| 4 | A | x |
| 4 | B | y |
| 5 | A | x |
| 5 | B | y |
| 5 | C | z |
| 5 | D | n |
| 6 | A | u |
| 6 | B | v |
| 7 | A | u |
| 7 | B | v |
+------+------+------+
现在我想获取 ids1
和3
for combine (A,x),(B,y),(C,z)
。我想获得ids2
和组合。ids和不同(因为缺少一行,因为一行太多),因此应单独报告:6
7
(A,u),(B,v)
4
5
1
4
5
(A,x),(B,y),(C,z): 1,3
(A,u),(B,v): 2,6,7
(A,x),(B,y): 4
(A,x),(B,y),(C,z),(D,n): 5
如何查询 MySQL 的这个分组?
用于设置示例表的 SQL 代码:
CREATE TABLE t (id int, a VARCHAR(4), b VARCHAR(4));
INSERT INTO t VALUES (1, 'A', 'x');
INSERT INTO t VALUES (1, 'B', 'y');
INSERT INTO t VALUES (1, 'C', 'z');
INSERT INTO t VALUES (2, 'A', 'u');
INSERT INTO t VALUES (2, 'B', 'v');
INSERT INTO t VALUES (3, 'A', 'x');
INSERT INTO t VALUES (3, 'B', 'y');
INSERT INTO t VALUES (3, 'C', 'z');
INSERT INTO t VALUES (4, 'A', 'x');
INSERT INTO t VALUES (4, 'B', 'y');
INSERT INTO t VALUES (5, 'A', 'x');
INSERT INTO t VALUES (5, 'B', 'y');
INSERT INTO t VALUES (5, 'C', 'z');
INSERT INTO t VALUES (5, 'D', 'n');
INSERT INTO t VALUES (6, 'A', 'u');
INSERT INTO t VALUES (6, 'B', 'v');
INSERT INTO t VALUES (7, 'A', 'u');
INSERT INTO t VALUES (7, 'B', 'v');
解决方案
id
我们可以首先使用Concat()
with获得特定组合中的所有组合Group_Concat()
。我们还可以确保将(a,b)
其视为与(b,a)
使用Greatest()
和Least()
功能相同。请注意,如果(b,a)
不应将其视为相同,那么您可以在下面的查询中(a,b)
摆脱Greatest()
and的使用。Least()
在 中Group_Concat()
,我们还对它们进行了排序,这样我们就不会得到两个单独的组合:(a,b), (c,d)
和(c,d), (a,b)
。订购确保我们只得到:(a,b), (c,d)
对于这两种情况。
最后,在派生表中使用此结果集,现在聚合具有相同组合集的所有 id。
架构(MySQL v5.7)
CREATE TABLE t (id int, a VARCHAR(4), b VARCHAR(4));
INSERT INTO t VALUES (1, 'A', 'x');
INSERT INTO t VALUES (1, 'B', 'y');
INSERT INTO t VALUES (1, 'C', 'z');
INSERT INTO t VALUES (2, 'A', 'u');
INSERT INTO t VALUES (2, 'B', 'v');
INSERT INTO t VALUES (3, 'A', 'x');
INSERT INTO t VALUES (3, 'B', 'y');
INSERT INTO t VALUES (3, 'C', 'z');
INSERT INTO t VALUES (4, 'A', 'x');
INSERT INTO t VALUES (4, 'B', 'y');
INSERT INTO t VALUES (5, 'A', 'x');
INSERT INTO t VALUES (5, 'B', 'y');
INSERT INTO t VALUES (5, 'C', 'z');
INSERT INTO t VALUES (5, 'D', 'n');
INSERT INTO t VALUES (6, 'A', 'u');
INSERT INTO t VALUES (6, 'B', 'v');
INSERT INTO t VALUES (7, 'A', 'u');
INSERT INTO t VALUES (7, 'B', 'v');
查询 #1
SELECT
dt.combinations,
GROUP_CONCAT(dt.id) AS ids
FROM
(
SELECT
GROUP_CONCAT(
DISTINCT
CONCAT('(', LEAST(a,b), ',', GREATEST(a,b), ')')
ORDER BY
CONCAT('(', LEAST(a,b), ',', GREATEST(a,b), ')') ASC) AS combinations,
id
FROM t
GROUP BY id
) dt
GROUP BY dt.combinations;
| combinations | ids |
| ----------------------- | ----- |
| (A,u),(B,v) | 2,6,7 |
| (A,x),(B,y) | 4 |
| (A,x),(B,y),(C,z) | 1,3 |
| (A,x),(B,y),(C,z),(D,n) | 5 |
推荐阅读
- javascript - 如何在 JSX 中访问路由器参数?
- sql - 根据日期从时间范围内获取数据
- android - 在使用带有 Retrofit 的 Post 调用时面临问题
- jenkins - Jenkins Pipeline - 在多个远程主机上并行运行作业
- ios - 如何为领域对象制作通用 GET 方法?
- python - Python 中的慢速 API 请求循环
- c# - 使用 javascript 在可移植对象本地化中获取当前语言
- javascript - 如何从现在的日期列表中查找下一个生日日期?
- php - 正则表达式匹配方括号之间的字符串,除了在特定的 html 标记内
- javascript - 为 db 中的每一行生成一个 case 开关