2014-01-14 17 views
10

MySQLデータベースに2つのテーブルがあるとします。複数の行を1つの行にまとめるMySQL

表1:

ID Name 
1  Jim 
2  Bob 
3  John 

表2:

ID key   value 
1  address  "X Street" 
1  city   "NY" 
1  region  "NY" 
1  country  "USA" 
1  postal_code "" 
1  phone   "123456789" 

データベースから行を選択する場合、最初の表に列として第2のテーブルからの行を結合する方法はありますか?

右MySQLのクエリからの望ましい結果は次のとおりです。任意のヘルプ

ID Name address city region country postal_code phone 
1  Jim  X Street NY  NY  USA  NULL   123456789 
2  Bob  NULL  NULL NULL  NULL  NULL   NULL 
3  John NULL  NULL NULL  NULL  NULL   NULL 

ありがとう!

答えて

23

このタイプのデータ変換はPIVOTとして知られています。 MySQLは、ピボット機能はありませんが、あなたはCASE式で集計関数を使用して、それを複製することができます。

select t1.id, 
    t1.name, 
    max(case when t2.`key` = 'address' then t2.value end) address, 
    max(case when t2.`key` = 'city' then t2.value end) city, 
    max(case when t2.`key` = 'region' then t2.value end) region, 
    max(case when t2.`key` = 'country' then t2.value end) country, 
    max(case when t2.`key` = 'postal_code' then t2.value end) postal_code, 
    max(case when t2.`key` = 'phone' then t2.value end) phone 
from table1 t1 
left join table2 t2 
    on t1.id = t2.id 
group by t1.id, t1.name 

SQL Fiddle with Demoを参照してください。

また、これはあなたのtable2に参加し、あなたが各keyのために参加する上でのフィルタが含まれる複数のを使って書くことができます

select t1.id, 
    t1.name, 
    t2a.value address, 
    t2c.value city, 
    t2r.value region, 
    t2y.value country, 
    t2pc.value postal_code, 
    t2p.value phone 
from table1 t1 
left join table2 t2a 
    on t1.id = t2a.id 
    and t2a.`key` = 'address' 
left join table2 t2c 
    on t1.id = t2c.id 
    and t2c.`key` = 'city' 
left join table2 t2r 
    on t1.id = t2r.id 
    and t2c.`key` = 'region' 
left join table2 t2y 
    on t1.id = t2y.id 
    and t2c.`key` = 'country' 
left join table2 t2pc 
    on t1.id = t2pc.id 
    and t2pc.`key` = 'postal_code' 
left join table2 t2p 
    on t1.id = t2p.id 
    and t2p.`key` = 'phone'; 

SQL Fiddle with Demoを参照してください。

key値の数が限られている場合、上記の2つのバージョンは効果的です。

| ID | NAME | ADDRESS | CITY | REGION | COUNTRY | POSTAL_CODE |  PHONE | 
|----|------|----------|--------|--------|---------|-------------|-----------| 
| 1 | Jim | X Street |  NY | (null) | (null) |  (null) | 123456789 | 
| 2 | Bob | (null) | (null) | (null) | (null) |  (null) | (null) | 
| 3 | John | (null) | (null) | (null) | (null) |  (null) | (null) | 

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'max(case when t2.`key` = ''', 
     `key`, 
     ''' then t2.value end) AS `', 
     `key`, '`' 
    ) 
) INTO @sql 
from Table2; 

SET @sql 
    = CONCAT('SELECT t1.id, t1.name, ', @sql, ' 
       from table1 t1 
       left join table2 t2 
       on t1.id = t2.id 
       group by t1.id, t1.name;'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

が結果を与えるSQL Fiddle with Demo

すべてのバージョンを参照してください:あなたは値の未知の数を持っている場合は、動的SQLを生成するために準備されたステートメントを使用して見たいと思うでしょう

+0

bluefeetこの動的クエリを実行すると、次のエラーメッセージが表示されます。 "#1243 - 不明なプリペアドステートメントハンドラstmt) " – n0nnus

+0

@ n0nnus残念ながら、私はあなたのデバッグを支援するMySQLの専門家ではありませんが、[リンク1](http://stackoverflow.com/questions/17418809/mysql-1243-error-while-phpmyadmin実行時エラー)、[リンク2](http://stackoverflow.com/questions/14840592/unknown-prepared-statement-handler-0-given-to-mysql -stmt-execute-in-php-code)と[リンク3](http:// stackoverflow。com/questions/16074952/mysql-1243-unknown-prepared-statement-handler-stmt-given-to-execute)を実行します。あなたはおそらくここやGoogleでエラーを解決するための助けを見つけるでしょう。とにかく – Taryn

+0

ありがとう! ;) – n0nnus

2

2番目のテーブルにentity-attribute-valueという構造があります。この組み合わせを行うには2つの方法があります。私は集計方法が表現しやすいと思う:

select t1.name, 
     max(case when `key` = 'address' then value end) as address, 
     max(case when `key` = 'city' then value end) as city, 
     max(case when `key` = 'region' then value end) as region, 
     max(case when `key` = 'country' then value end) as country, 
     max(case when `key` = 'postal_code' then value end) as postal_code, 
     max(case when `key` = 'phone' then value end) as phone 
from table1 t1 left join 
    table2 t2 
    on t1.id = t2.id 
group by t1.name; 

第2の方法は、別のやっている各値に対して加入:

select t1.name, address.value, city.value, . . . 
from table1 t1 left join 
    table2 address 
    on t1.id = address.id and address.`key` = 'Address' left join 
    table2 city 
    on t1.id = city.id and city.`key` = 'City' . . . 

データの構造によっては、join方法は、実際にすることができます適切な索引付けを使用すると、MySQLで高速になります。 (group byメソッドは他のデータベースでよく機能します)

+0

私はここで#1のアプローチ(caseステートメントを使用)がこれで動作しないように見えるのはなぜか不思議です(http://stackoverflow.com/questions/23377374/using-case-to-convert-column- values-to-row-values-in-mysqlの場合)? – JackhammersForWeeks

関連する問題