2013-03-21 50 views
3

這裏有點複雜。我一直在四處看看如何使用結果作爲列名,雖然看起來可能,但我發現的所有示例都使用了非常簡單的表格設計。MySQL列名稱作爲與結點表的多對多關係的字段名稱

我得到的是3張桌子。

我們有一個'訂單'表,它可以有'order_extras'。 'extras'表存儲額外名稱和價格,'order_extras'基本上包含主鍵,訂單ID和額外ID。

的這個粗略圖形表示如下:enter image description here

使用這個作爲一個例子,讓我們假設該「額外」表被填充了3個額外的項的名稱和價格是在該階段不相關的。

我想要做的是得到所有的訂單,但是每個額外項目的名稱都有額外的列。如果已購買該物品(又稱爲order_extras表格),則會顯示價格,否則它將爲空/空。

這甚至可能嗎?我一直在研究數據透視表,但這類信息似乎有點不穩定。任何信息或建議將不勝感激!

實施例數據

額外:

+----+------------------+--------+ 
| id |  name  | price | 
+----+------------------+--------+ 
| 1 | Insurance  | 59.95 | 
| 2 | Lifetime Updates | 79.95 | 
| 3 | Phone Support | 124.95 | 
+----+------------------+--------+ 

訂單:

+----+------------+ 
| id | customer | 
+----+------------+ 
| 1 | John Smith | 
| 2 | Bob Newbie | 
| 3 | Bill Jobs | 
| 4 | Ray Stantz | 
+----+------------+ 

order_extras:

+----+----------+----------+ 
| id | order_id | extra_id | 
+----+----------+----------+ 
| 1 |  4 |  2 | 
| 2 |  3 |  1 | 
| 3 |  3 |  3 | 
| 4 |  1 |  1 | 
+----+----------+----------+ 

期望輸出:

+----------+----------------+-----------+------------------+---------------+ 
| order.id | order.customer | Insurance | Lifetime Updates | Phone Support | 
+----------+----------------+-----------+------------------+---------------+ 
|  1 | John Smith  | 59.95  | 0    | 0    | 
|  2 | Bob Newbie  | 0   | 0    | 0    | 
|  3 | Bill Jobs  | 59.95  | 0    | 124.95  | 
|  4 | Ray Stantz  | 0   | 79.95   | 0    | 
+----------+----------------+-----------+------------------+---------------+ 
+0

你可以張貼一些示例數據和預期的結果?理解你在做什麼而不閱讀單詞問題可能會更容易。 :) – Taryn 2013-03-21 21:13:09

+1

從我可以告訴,MySQL不支持任何類型的樞軸關鍵字或「真正」樞軸。看看這個帖子。這傢伙寫了一個瘋狂的sproc來處理它:http://stackoverflow.com/questions/6158230/mysql-pivot-table-with-dynamic-headers-based-on-single-column-data – 2013-03-21 21:21:27

+0

剛剛更新了第一篇文章我希望做的一些例子 – Sk446 2013-03-21 21:34:01

回答

2

不幸的是,MySQL不具有樞軸功能,但可以使用聚合官能團與CASE表達被複制。

如果你有一個已知數量的extras,那麼你可以硬編碼查詢:

select o.id, 
    o.customer, 
    max(case when e.name = 'Insurance' then e.price else 0 end) Insurance, 
    max(case when e.name = 'Lifetime Updates' then e.price else 0 end) `Lifetime Updates`, 
    max(case when e.name = 'Phone Support' then e.price else 0 end) `Phone Support` 
from orders o 
left join order_extras oe 
    on o.id = oe.order_id 
left join extras e 
    on oe.extra_id = e.id 
group by o.id, o.customer 

SQL Fiddle with Demo

對於你的情況,看起來你會有一個未知數的值。如果是這樣的話,那麼你將需要使用準備好的語句來生成動態SQL:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'max(CASE WHEN e.name = ''', 
     name, 
     ''' THEN e.price else 0 END) AS `', 
     name, '`' 
    ) 
) INTO @sql 
FROM extras; 

SET @sql 
    = CONCAT('SELECT o.id, 
       o.customer, ', @sql, ' 
      from orders o 
      left join order_extras oe 
       on o.id = oe.order_id 
      left join extras e 
       on oe.extra_id = e.id 
      group by o.id, o.customer'); 

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

SQL Fiddle with Demo

這兩個版本會給結果:

| ID | CUSTOMER | INSURANCE | LIFETIME UPDATES | PHONE SUPPORT | 
------------------------------------------------------------------ 
| 1 | John Smith |  59.95 |    0 |    0 | 
| 2 | Bob Newbie |   0 |    0 |    0 | 
| 3 | Bill Jobs |  59.95 |    0 |  124.95 | 
| 4 | Ray Stantz |   0 |   79.95 |    0 | 
+1

首先感謝第二個例子 - 多數民衆贊成!我試着通過本地數據庫運行它,並且查詢成功運行,但實際上並沒有返回任何內容。有點奇怪,它顯然工作,因爲它顯示行數,但沒有任何結果列出。在phpMyAdmin和Mac應用程序'Sequel Pro'中嘗試了這個:/ – Sk446 2013-03-22 10:41:45

+0

@RickM您是否嘗試將此代碼放入過程中? – Taryn 2013-03-22 11:21:45

+0

這很奇怪 - 如果我將它作爲標準查詢運行,它不會輸出任何內容。不過謝天謝地,我想把它導出到CSV。使用outfile,它完美的工作! – Sk446 2013-03-22 15:08:04

1

試試這個。

select o.id , o.customer , 
    max(if(e.name = 'Insurance' , round(e.price,2), 0)) as Insurance, 
    max(if(e.name = 'Lifetime Updates' , round(e.price,2), 0)) as Lifetime_Updates, 
    max(if(e.name = 'Phone Support' , round(e.price,2), 0)) as Phone_Support 

    from orders o 
    left join order_extras oe 
    on o.id = oe.order_id 
    left join Extras e 
    on oe.extra_id = e.id 

    group by o.id, o.customer 

DEMO HERE

輸出是:

ID CUSTOMER INSURANCE LIFETIME_UPDATES PHONE_SUPPORT 
    1 John Smith 59.95    0    0 
    2 Bob Newbie  0    0    0 
    3 Bill Jobs 59.95    0    124.95 
    4 Ray Stantz  0    79.95    0