2014-01-14 133 views
10

假設我在MySQL數據庫中有兩個表。將多行組合成一行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" 

當從數據庫中選擇的行,是否有任何方式加入從第二表作爲列的行到第一表?

權從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數值有限,上述兩個版本將很有用。如果你有一個未知的數值,那麼你將要看看使用準備好的語句來生成動態SQL:

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

所有版本會給結果:

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

bluefeet,當我運行這個動態查詢,它給了我這個錯誤消息: 「#1243-未知的預處理語句處理程序stmt)給EXECUTE「 – n0nnus

+0

@ n0nnus不幸的是,我不是MySQL專家來幫助您調試,但我在這裏發現了一些其他問題,可能有助於[鏈接1](http://stackoverflow.com/questions/17418809/mysql-1243-while-execution-it-through-phpmyadmin),[Link 2](http://stackoverflow.com/questions/14840592/unknown-prepared-statement-handler-0-given-to-mysql -stmt-execute-in-php-code)和[Link 3](http:// stackoverflow。COM /問題/ 16074952/MySQL的-1243-未知準備語句處理程序,語句賦予到執行)。您可能會在這裏找到一些幫助或谷歌來解決這個錯誤。 – Taryn

+0

thankz反正! ;) – n0nnus

2

你在第二個表中有一個叫做entity-attribute-value的結構。有兩種方法可以進行組合。我覺得聚集方法是更容易表達:

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; 

第二種方法是做單獨連接每個值:

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-值到行值-in-mysql)的情況? – JackhammersForWeeks