2012-08-05 116 views
4

我有2個表格,Main和Units。SQL:如何根據同一表中的其他列的值創建新列

主表:

Todate Unit CategoryID Quantity 
1/7/2012 1  S   300 
1/7/2012 1  U   350 
2/7/2012 2  S   220 
3/7/2012 2  S    50 
3/7/2012 2  U   330 
4/7/2012 1  S   200 
4/7/2012 1  U   180 

S =銷售,U =升級

單位表:

UnitNum UnitName 
1   Measures 
2   Performance 

我需要得到這樣的結果:

Todate UnitNum UnitName Sales Upgrades 
1/7/2012 1  Measures  300  350 
2/7/2012 2  Performance 220 
3/7/2012 2  Performance 50  330 
4/7/2012 1  Measures  200  180 

意義我需要創建2列 - 銷售和升級,這取決於CategoryID中的值,我需要它們在同一行中。 我有什麼到目前爲止,這是

select Todate, Main.Unit, UnitName, 
case when CategoryID = 'S' then Quantity end as Sales, 
case when CategoryID = 'U' then Quantity end as Upgrades 
from Main join Units on Main.UnitNum = Units.UnitNum 
group by Todate, Main.Unit, UnitName 

它給了我2個新列,但它們是兩個獨立的行..

我真的很感激任何幫助解決這一! 謝謝

+0

我真的建議你使用主索引(唯一)的分類。而不是U和S使另一個名爲類別的表包含銷售和升級,並在主表中存儲每行的主要id在類別中。 – 2012-08-05 20:05:49

+0

Matei Mihai,我沒有創建這個,這只是一個問題,我被問及不能回答 – Cat 2012-08-05 20:11:29

+0

有沒有一個情況可能是2(或更多)行與'Todate'相同,相同'Unit'和相同'CategoryID'? – 2012-08-05 20:23:33

回答

1

您只需要圍繞case語句進行聚合查詢。

select m.todate 
    , m.unit 
    , u.unitname 
    , sum(case when m.categoryid = 'S' then quantity end) as sales 
    , sum(case when m.categoryid = 'U' then quantity end) as upgrages 
    from main m 
    join units u 
    on m.unit = u.unitnum 
group by m.todate, m.unit, u.unitname 
+0

嗨本,謝謝,但我仍然得到相同的結果 – Cat 2012-08-05 20:12:40

+0

嗯,你是對的,這不會給預期的結果,但只是因爲你似乎已經選擇了一個隨機的'單位名稱'。這意味着你應該圍繞這個列進行綜合查詢,並將它從「group by」中移除,但是在你的預期結果集中你沒有明確的理由。他們爲什麼如預期的那樣? – Ben 2012-08-05 20:18:55

+0

您的意思是UnitName不必在結果集中出現?這是預期的結果集,我只是複製了這個問題,因爲它是 – Cat 2012-08-05 20:24:55

0

你需要做一個與自己的主表的自聯接:

SELECT m1.todate, m1.unit AS unitnum, u.unitname, 
     SUM(m1.quantity) AS sales, SUM(m2.quantity) AS upgrades 
    FROM (SELECT todate, unit, quantity FROM Main WHERE category = 'S') AS m1 
    FULL OUTER JOIN 
     (SELECT todate, unit, quantity FROM Main WHERE category = 'U') AS m2 
    ON m1.todate = m2.todate AND m1.unit = m2.unit 
    JOIN units AS u 
    ON m1.unit = u.unitnum 
    GROUP BY m1.todate, m1.unit, u.unitname 
    ORDER BY m1.todate, m1.unit, u.unitname; 

有編寫相同的查詢的許多其他等效方法;儘管如此,這個問題還是很好地保留了問題的對稱性。 (更新使用完全外部的m1m2子查詢之間的連接,以應對那裏有銷售沒有升級或升級,沒有銷售的情況下

+0

這個版本忽略了我只有銷售(2/7/2012 2 220)的行,它沒有出現在結果中。另外,如果我添加沒有單元號的行,它會完全忽略它們。 – Cat 2012-08-05 21:14:18

+0

如果沒有單元號的不完整行,你會做什麼?處理另一個問題是一個麻煩 - 你需要一個完整的外部聯接(假設你只能在任何一天有銷售或升級)。 – 2012-08-05 23:02:36

1

你需要的東西是這樣的:

SELECT 
    Todate, m.Unit, UnitName, 
    Sales = (SELECT SUM(Quantity) 
      FROM dbo.Main m2 
      WHERE m.Todate = m2.Todate AND CategoryID = 'S'), 
    Updates = (SELECT SUM(Quantity) 
       FROM dbo.Main m2 
       WHERE m.Todate = m2.Todate AND CategoryID = 'U') 
FROM 
    dbo.Main m 
INNER join 
    dbo.Units u on m.Unit = u.UnitNum 
GROUP BY 
    Todate, m.Unit, UnitName 
ORDER BY 
    Todate, m.Unit, UnitName 

這似乎是回到你要找的輸出:

enter image description here

+0

看起來真的很接近,但是如果我在單位爲空的情況下添加另一行,例如:2012年4月7日,null,S,15,它應該被添加爲另一行,但是您的代碼會將其添加到總和最後一行,我得到了2012-04-07 1措施215 180 – Cat 2012-08-05 21:07:12

+0

@Cat:當你添加這一行時你期望什麼?它會被添加到(1)給定的(2012年4月7日)的「Todate」,以及根據「CategoryID」添加到銷售或更新列 - 但是在您的問題中,您沒有明確說明「單元'在這裏是相關的.....什麼**應該**發生在一行'(2012年4月7日,NULL,'S',15)'?它應該加到總和上嗎?還是被忽略?還有什麼? – 2012-08-06 05:04:03

+0

對不起,我從一開始就不清楚。如果未指定單位,則不應將其添加到另一行的總和中,而應該添加爲另一行。我在一次採訪中被問到了這個問題,我不知道具體的規則,我只是按照我給出的預期結果行事。有「無單位」的行被單獨顯示爲一行。 – Cat 2012-08-07 11:44:34

0

你可以使用PIVOT也是這樣的:

WITH data AS (
    SELECT 
    m.Todate, 
    m.UnitNum, 
    u.UnitName, 
    Category = CASE m.CategoryID 
       WHEN 'S' THEN 'Sales' 
       WHEN 'U' THEN 'Upgrades' 
       END, 
    Quantity 
    FROM Main m 
    INNER JOIN Units u 
    ON m.UnitNum = u.UnitNum 
) 
SELECT 
    Todate, 
    UnitNum, 
    UnitName, 
    Sales, 
    Upgrades 
FROM data 
PIVOT (
    SUM(Quantity) FOR Category IN (Sales, Upgrades) 
) p 
;