首页 > 解决方案 > 如何在 MySQL SELECT 中按“行集”分组?

问题描述

我有t包含列组合的表a,并且bid分配。这些组合在a重复b。对于每个这样的组合,我想确定所有ids。例子:

+------+------+------+
| 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    |
+------+------+------+

现在我想获取 ids13for combine (A,x),(B,y),(C,z)。我想获得ids2和组合。ids和不同(因为缺少一行,因为一行太多),因此应单独报告:67(A,u),(B,v)45145

(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');

标签: mysql

解决方案


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     |

在 DB Fiddle 上查看


推荐阅读