web-dev-qa-db-ja.com

group_concatおよび一緒にグループ化

group_concatconcatなどの関数を使用してクエリを作成しようとしていますが、データを結合してグループ化して1つのセルで表すことができないという問題が発生しています。

これが私のデータです...

table1
+-----+---------+
| id  | ...     |
+-----+---------+
| 1   |         |
| 2   |         |
| 3   |         |
+-----+---------+
table2
+-----+-----+-------+
| id  | env | infid |
+-----+-----+-------+
| 1   | p   | 10    |
| 1   | p   | 11    |
| 1   | p   | 20    |
| 1   | p   | 12    |
| 1   | D   | 21    |
| 1   | D   | 22    |
+-----+-----+-------+
table3
+-------+---------+---------+
| infid | inftype | infname |
+-------+---------+---------+
| 10    | Srv     | abc     |
| 20    | Srv     | xyz     |
| 11    | Db      | hgj     |
| 12    | Db      | kjk     |
| 21    | Srv     | pop     |
| 22    | Db      | kli     |
+-------+---------+---------+

予想されるクエリ結果

+-----+------------------------------+---------------------+
| id  | P                            | D                   |
+------------------------------------+---------------------+
| 1   |Srv: [abc, xyz] Db: [hgj, kjk]|Srv: [pop] Db: [Kli] |
+-----+------------------------------+---------------------+

どんな助けでも大歓迎です。

6
Kumar

最初に必要なのは、各列を作成するための面倒なクエリです

クエリの最初のフェーズ

SELECT env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
ORDER BY inftype DESC SEPARATOR ' ') tags
FROM (SELECT env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
FROM table1 AAA
INNER JOIN table2 BBB ON AAA.id = BBB.id
INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
GROUP BY env,inftype) A GROUP BY env;

あなたのサンプルデータ

mysql> DROP DATABASE IF EXISTS kumar_concat;
Query OK, 3 rows affected (0.03 sec)

mysql> CREATE DATABASE kumar_concat;
Query OK, 1 row affected (0.00 sec)

mysql> USE kumar_concat
Database changed
mysql> CREATE TABLE table1
    -> (
    ->     id INT NOT NULL AUTO_INCREMENT,
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO table1 VALUES (),(),();
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> CREATE TABLE table2
    -> (
    ->     id INT NOT NULL,
    ->     env VARCHAR(10) NOT NULL,
    ->     infid INT NOT NULL,
    ->     PRIMARY KEY (id,infid)
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTO table2 (id,env,infid) VALUES
    -> (1,'P',10), (1,'P',11), (1,'P',20),
    -> (1,'P',12), (1,'D',21), (1,'D',22);
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> CREATE TABLE table3
    -> (
    ->     infid INT NOT NULL,
    ->     inftype VARCHAR(10) NOT NULL,
    ->     infname VARCHAR(10) NOT NULL,
    ->     PRIMARY KEY (infid)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO table3 (infid,inftype,infname) VALUES
    -> (10,'Srv','abc'), (20,'Srv','xyz'), (11,'Db','hgj'),
    -> (12,'Db','kjk'), (21,'Srv','pop'), (22,'Db','kli');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql>

クエリの最初のフェーズが実行されました

mysql> SELECT env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
    -> ORDER BY inftype DESC SEPARATOR ' ') tags
    -> FROM (SELECT env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
    -> FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
    -> FROM table1 AAA
    -> INNER JOIN table2 BBB ON AAA.id = BBB.id
    -> INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
    -> GROUP BY env,inftype) A GROUP BY env;
+-----+------------------------------+
| env | tags                         |
+-----+------------------------------+
| D   | Srv [pop] Db [kli]           |
| P   | Srv [abc, xyz] Db [hgj, kjk] |
+-----+------------------------------+
2 rows in set (0.02 sec)

mysql>

それぞれのenv値ごとに作成しましょう

クエリ

SELECT
    T1.tags P,T2.tags D
FROM
(SELECT env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
ORDER BY inftype DESC SEPARATOR ' ') tags
FROM (SELECT env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
FROM table1 AAA
INNER JOIN table2 BBB ON AAA.id = BBB.id
INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
GROUP BY env,inftype) A GROUP BY env) T1,
(SELECT env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
ORDER BY inftype DESC SEPARATOR ' ') tags
FROM (SELECT env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
FROM table1 AAA
INNER JOIN table2 BBB ON AAA.id = BBB.id
INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
GROUP BY env,inftype) A GROUP BY env) T2
WHERE T1.env='P'
AND T2.env='D';

実行されたクエリ

mysql> SELECT
    ->     T1.tags P,T2.tags D
    -> FROM
    -> (SELECT env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
    -> ORDER BY inftype DESC SEPARATOR ' ') tags
    -> FROM (SELECT env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
    -> FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
    -> FROM table1 AAA
    -> INNER JOIN table2 BBB ON AAA.id = BBB.id
    -> INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
    -> GROUP BY env,inftype) A GROUP BY env) T1,
    -> (SELECT env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
    -> ORDER BY inftype DESC SEPARATOR ' ') tags
    -> FROM (SELECT env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
    -> FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
    -> FROM table1 AAA
    -> INNER JOIN table2 BBB ON AAA.id = BBB.id
    -> INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
    -> GROUP BY env,inftype) A GROUP BY env) T2
    -> WHERE T1.env='P'
    -> AND T2.env='D';
+------------------------------+--------------------+
| P                            | D                  |
+------------------------------+--------------------+
| Srv [abc, xyz] Db [hgj, kjk] | Srv [pop] Db [kli] |
+------------------------------+--------------------+
1 row in set (0.05 sec)

mysql>

最終クエリ(IDが差し込まれている)

SELECT
    T1.id,T1.tags P,T2.tags D
FROM
(SELECT id,env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
ORDER BY inftype DESC SEPARATOR ' ') tags
FROM (SELECT id,env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
FROM table1 AAA
INNER JOIN table2 BBB ON AAA.id = BBB.id
INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
GROUP BY id,env,inftype) A GROUP BY id,env) T1
INNER JOIN
(SELECT id,env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
ORDER BY inftype DESC SEPARATOR ' ') tags
FROM (SELECT id,env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
FROM table1 AAA
INNER JOIN table2 BBB ON AAA.id = BBB.id
INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
GROUP BY id,env,inftype) A GROUP BY id,env) T2 
USING (id) WHERE T1.env='P' AND T2.env='D';

最終クエリ(IDが差し込まれている)が実行されました

mysql> SELECT
    ->     T1.id,T1.tags P,T2.tags D
    -> FROM
    -> (SELECT id,env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
    -> ORDER BY inftype DESC SEPARATOR ' ') tags
    -> FROM (SELECT id,env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
    -> FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
    -> FROM table1 AAA
    -> INNER JOIN table2 BBB ON AAA.id = BBB.id
    -> INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
    -> GROUP BY id,env,inftype) A GROUP BY id,env) T1
    -> INNER JOIN
    -> (SELECT id,env,GROUP_CONCAT(CONCAT(inftype,' [',names,']')
    -> ORDER BY inftype DESC SEPARATOR ' ') tags
    -> FROM (SELECT id,env,inftype,GROUP_CONCAT(infname ORDER BY infname SEPARATOR ', ') names
    -> FROM (SELECT AAA.id,BBB.infid,BBB.env,CCC.inftype,CCC.infname
    -> FROM table1 AAA
    -> INNER JOIN table2 BBB ON AAA.id = BBB.id
    -> INNER JOIN table3 CCC ON BBB.infid = CCC.infid) AA
    -> GROUP BY id,env,inftype) A GROUP BY id,env) T2
    -> USING (id) WHERE T1.env='P' AND T2.env='D';
+----+------------------------------+--------------------+
| id | P                            | D                  |
+----+------------------------------+--------------------+
|  1 | Srv [abc, xyz] Db [hgj, kjk] | Srv [pop] Db [kli] |
+----+------------------------------+--------------------+
1 row in set (0.08 sec)

mysql>

試してみる !!!

2
RolandoMySQLDBA

より簡単な方法で目的の結果を得ることができます。

まず、次の簡単なクエリから始めます。

SELECT
  t1.id,
  t2.env,
  CONCAT(t3.inftype,
         ': [',
         GROUP_CONCAT(t3.infname ORDER BY t3.infname SEPARATOR ', '),
         ']'
        ) AS inftypeandnames
FROM
  table1 AS t1
  INNER JOIN table2 AS t2 ON t1.id = t2.id
  INNER JOIN table3 AS t3 ON t2.infid = t3.infid
GROUP BY
  t1.id,
  t2.env,
  t3.inftype

これは、データサンプルに対して 結果として を取得するものです。

id  env  inftypeandnames
--  ---  ---------------
1   D    Db: [kli]
1   D    Srv: [pop]
1   P    Db: [hgj, kjk]
1   P    Srv: [abc, xyz]

次に、上記の結果を派生テーブルとして使用し、id, envでグループ化し、inftypeandnames値を連結して、次のようにすることができます。

SELECT
  id,
  env,
  GROUP_CONCAT(inftypeandnames ORDER BY inftypeandnames DESC SEPARATOR ' ') AS inftypesandnames
FROM
  (
    SELECT
      t1.id,
      t2.env,
      CONCAT(t3.inftype,
             ': [',
             GROUP_CONCAT(t3.infname ORDER BY t3.infname SEPARATOR ', '),
             ']'
            ) AS inftypeandnames
    FROM
      table1 AS t1
      INNER JOIN table2 AS t2 ON t1.id = t2.id
      INNER JOIN table3 AS t3 ON t2.infid = t3.infid
    GROUP BY
      t1.id,
      t2.env,
      t3.inftype
  ) AS s
GROUP BY
  id,
  env

結果は非常に近いでしょう あなたが望むものに:

id  env  inftypesandnames
--  ---  ------------------------------
1   D    Srv: [pop] Db: [kli]
1   P    Srv: [abc, xyz] Db: [hgj, kjk]

inftypesandnamesの値をenvの値に基づいて個別の列に分割するには、上記のクエリを複製して、各コピーにenvにフィルターを適用します(env = 'D'env = 'P'など、他にも存在する可能性がある場合)、結果を結合して、各サブセットのinftypesandnames値を独自の列に返します– Rolandoの提案と同じ 、ただし、一部のidsにDしかなく、一部のPのみが可能である場合、内部結合ではなく完全外部結合が必要になる可能性があると主張します。 。 MySQLはFULL JOIN/FULL OUTER JOIN構文をサポートしていないため、これに対する通常の回避策は左結合と右結合の和集合です。もっと。

ただし、条件付き集計を使用して結果をピボットできるため、このようなサブクエリの複製に頼る必要はありません。外部クエリでid, envでグループ化する代わりに、idのみでグループ化し、inftypeandnamesに基づいてGROUP_CONCATをenv値に条件付きで適用します。 :

SELECT
  id,
  GROUP_CONCAT(CASE env WHEN 'P' THEN inftypeandnames END ORDER BY inftypeandnames DESC SEPARATOR ' ') AS P,
  GROUP_CONCAT(CASE env WHEN 'D' THEN inftypeandnames END ORDER BY inftypeandnames DESC SEPARATOR ' ') AS D
FROM
  (
    SELECT
      t1.id,
      t2.env,
      CONCAT(t3.inftype,
             ': [',
             GROUP_CONCAT(t3.infname ORDER BY t3.infname SEPARATOR ', '),
             ']'
            ) AS inftypeandnames
    FROM
      table1 AS t1
      INNER JOIN table2 AS t2 ON t1.id = t2.id
      INNER JOIN table3 AS t3 ON t2.infid = t3.infid
    GROUP BY
      t1.id,
      t2.env,
      t3.inftype
  ) AS s
GROUP BY
  id
;

自分で確認 最後のクエリの結果が要件に一致することを確認します。

id  P                               D
--  ------------------------------  --------------------
1   Srv: [abc, xyz] Db: [hgj, kjk]  Srv: [pop] Db: [kli]
7
Andriy M

これらの例はGROUP_CONCATで使用できます。

クエリ1:

SELECT
    t1.id,
    t2.env,
    CASE WHEN t2.env='P' THEN GROUP_CONCAT(CONCAT(t3.inftype,': [',t3.infname,'] ') SEPARATOR ' ') 
     WHEN t2.env='D' THEN GROUP_CONCAT(CONCAT(t3.inftype,': [',t3.infname,'] ') SEPARATOR ' ') END AS 'infname'
FROM test.table1 as t1
JOIN test.table2 as t2 ON (t2.id=t1.id)
JOIN test.table3 as t3 ON (t2.infid=t3.infid)
GROUP BY t1.id,t2.env;

結果Q1:

+----+-----+-----------------------------------------------+
| id | env | infname                                           |
+----+-----+-----------------------------------------------+
|  1 | D   | Db: [kli]  Srv: [pop]                         |
|  1 | P   | Srv: [xyz]  Db: [kjk]  Db: [hgj]  Srv: [abc]  |
+----+-----+-----------------------------------------------+
2 rows in set (0.00 sec)

クエリ2:

SELECT
    t1.id,
    t2.env,
    GROUP_CONCAT(CONCAT(t3.inftype,': [',t3.infname,'] ') SEPARATOR ' ') AS infname
FROM test.table1 as t1
JOIN test.table2 as t2 ON (t2.id=t1.id)
JOIN test.table3 as t3 ON (t2.infid=t3.infid)
GROUP BY t1.id,t2.env;

結果Q2:

+----+-----+-----------------------------------------------+
| id | env | infname                                       |
+----+-----+-----------------------------------------------+
|  1 | D   | Db: [kli]  Srv: [pop]                         |
|  1 | P   | Db: [hgj]  Db: [kjk]  Srv: [abc]  Srv: [xyz]  |
+----+-----+-----------------------------------------------+
2 rows in set (0.00 sec)
0
oNare