web-dev-qa-db-ja.com

単一行への1対多のSQL SELECT

2つのテーブルにデータがあります。

最初のテーブルにはPKIDと呼ばれる主キーがあります

PKID  DATA
0    myData0
1    myData1
2    myData2

2番目のテーブルには、テーブル1のPKID列が外部キーとして含まれています。

PKID_FROM_TABLE_1  U_DATA
       0          unique0
       0          unique1        
       0          unique2
       1          unique3
       1          unique4
       1          unique5
       2          unique6
       2          unique7
       2          unique8

現在作成している基本的なSELECTステートメントは

SELECT a.PKID, a.DATA, b.U_DATA
FROM table1 as a
INNER JOIN table2 as b
ON a.PKID = b.PKID_FROM_TABLE_1

これにより、次のようなテーブルが生成されます。

PKID   DATA     U_DATA
 0   myData0    unique0
 0   myData0    unique1
 0   myData0    unique2
 1   myData1    unique3
 1   myData1    unique4
 1   myData1    unique5
 2   myData2    unique6
 2   myData2    unique7
 2   myData2    unique8

私が欲しいのは次の表です:

PKID   DATA    U_DATA1    U_DATA2    U_DATA3
 0     myData0 unique0    unidque1   unique2
 1     myData1 unique3    unidque4   unique5
 2     myData2 unique6    unidque7   unique8

それが役立つ場合、各PKIDはtable2にちょうど3つのエントリを持ちます。

MySQLでこのようなことは可能ですか?

24
Grizz

これは結果を取得する1つの方法です。

このアプローチでは、相関サブクエリを使用します。各サブクエリはORDER BY句を使用してtable2から関連する行を並べ替え、LIMIT句を使用して1行目、2行目、3行目を取得します。

SELECT a.PKID
     , a.DATA
     , (SELECT b1.U_DATA FROM table2 b1
         WHERE b1.PKID_FROM_TABLE_1 = a.PKID 
         ORDER BY b1.U_DATA LIMIT 0,1
       ) AS U_DATA1
     , (SELECT b2.U_DATA FROM table2 b2
         WHERE b2.PKID_FROM_TABLE_1 = a.PKID 
         ORDER BY b2.U_DATA LIMIT 1,1
       ) AS U_DATA2
     , (SELECT b3.U_DATA FROM table2 b3
         WHERE b3.PKID_FROM_TABLE_1 = a.PKID 
         ORDER BY b3.U_DATA LIMIT 2,1
       ) AS U_DATA3
  FROM table1 a
 ORDER BY a.PKID  

ファローアップ

@ gliese581gは、SELECTリストの各サブクエリが外部クエリで返される各行に対して実行されるため、外部クエリによって返される行数が多い場合、このアプローチではパフォーマンスの問題が発生する可能性があることを指摘しています。

言うまでもなく、このアプローチはインデックスを求めて叫びます。

ON table2 (PKID_FROM_TABLE_1, U_DATA)

-または、少なくとも-

ON table2 (PKID_FROM_TABLE_1)

外部キーが定義されている場合、後者のインデックスはすでに存在している可能性があります。前者のインデックスでは、並べ替え操作( "filesortの使用")を必要とせずに、インデックスページからクエリを完全に満たすことができます( "インデックスの使用")。

@ glies581gは、このアプローチのパフォーマンスが「大きな」セットで問題になる可能性があることを指摘するのはかなり正しいです。

19
spencer7593

MySQLのリリースに応じて、GROUP_CONCATを調べることができます

8
sdfor