group_concat
、concat
などの関数を使用してクエリを作成しようとしていますが、データを結合してグループ化して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] |
+-----+------------------------------+---------------------+
どんな助けでも大歓迎です。
最初に必要なのは、各列を作成するための面倒なクエリです
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>
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';
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>
より簡単な方法で目的の結果を得ることができます。
まず、次の簡単なクエリから始めます。
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の提案と同じ 、ただし、一部のid
sに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]
これらの例は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)