2012-08-06 58 views
0

我正在嘗試使用SQL查找表中特定值的總和。示例表是:SQL中特定值的總和

+-------+-------+-------+-------+-------+-------+-------+ 
| ID | Co1 | Va1 | Co2 | Va2 | Co3 | Va3 | 
+-------+-------+-------+-------+-------+-------+-------+ 
| 01 | AA1 | 23.0| AA2 | 11.2| AA3 | 328.34| 
| 02 | AA2 | 27.0| AA3 | 234.56| AA4 | 23.8| 
| 03 | AA1 | 409.01| AA4 | 234.98| NULL | NULL | 
+-------+-------+-------+-------+-------+-------+-------+ 

我有35個這樣的'代碼'列和值。

我需要的是選擇一個只有一個代碼的表。說我需要代碼AA3,這將是(這裏不需要代碼列,但只顯示在那裏我得到的值):

+-------+-------+--------+ 
| ID | Code | Value | 
+-------+-------+--------+ 
| 01 | AA3 | 328.34| 
| 02 | AA3 | 234.56| 
| 03 | AA3 |  0| 
+-------+-------+--------+ 

我稍後會需要另一個(獨立)查詢包含總和幾個代碼,例如代碼AA1和AA2的總和。

+-------+---------+ 
| ID | Value | 
+-------+---------+ 
| 01 |  34.2| 
| 02 |  27.0| 
| 03 | 409.01| 
+-------+---------+ 

我在考慮讓每個35列都有一個'WHERE',但這真的很乏味,而且看起來效率不高。我想知道是否有辦法通過SQL來做到這一點(我可以用Excel來做到這一點,它會產生奇蹟)。

也許如果有一種方法可以通過一行「搜索」,返回列名稱,然後使用該列名稱檢索數字?

讓我知道如果你需要更多的信息=)

+0

, SQL Server,Oracle,MySQL?在第一個句子中,你說「使用SQL」,你的意思是MS SQL Server?在最後一個問題中,你是否只有3個代碼列? SUM僅適用於AA1和AA2或更多組合? – Yaroslav 2012-08-06 09:02:17

+0

啊,是的,我的壞。這是我正在使用的SQL Server 2008R2。 – Jerry 2012-08-06 09:31:25

+0

出於某種原因,我沒有看到您的其他評論......哦,好吧。是的,實際上有35個代碼列和35個數量列。代碼從AA1到AA652不等。對於第二部分(添加幾個代碼),我需要添加9個代碼:AA74,AA76,AA78等。 – Jerry 2012-08-06 10:12:54

回答

2

你應該做的是店規範化形式您的數據。

但是......

select SUM(v) 
from 
(

select * -- ID, r, v 
from 
(select * from yourtable) u 
unpivot 
(r for co in (co1, co2, co3)) as u1 
unpivot 
( v for va in (va1, va2, va3)) as u2 
where RIGHT(co,1) = RIGHT(va,1) 
) v 
WHERE R = 'AA1' -- etc 

將返回尋求

+0

我希望它被正常化! >。<這會更簡單。 嗯,你能爲我解釋一下嗎?我對SQL很陌生(^^;) 例如,'FOR'會循環嗎?我不確定爲什麼你在WHERE語句的'值'中從右邊開始了左邊的字符...... – Jerry 2012-08-06 09:48:45

+0

UNPIVOT採用一個非規範化的表格,並對其進行標準化(即:使其更加垂直,水平更低) 。但是它只能執行一種數據類型,所以你需要做兩次才能得到兩種類型。 RIGHT將文本數據(CO1,CO2)的最後一個字符與數值數據(VA1,VA2)的最後一個字符相匹配。嘗試用*替換SUM(V)以查看整個數據集 – podiluska 2012-08-06 10:00:18

+0

啊!我認爲你正在取值列值並取最後一個字符!通過選擇所有我現在明白它實際上是您匹配的列名稱。謝謝!這樣可行! :D(除了我在SQL服務器導入的列數據類型不匹配......哦,我必須重新正確地重新導入它們) – Jerry 2012-08-06 10:35:08

0

你的表結構的結果不太理想。我將向您展示一個類似於基於Excel的IF方法的直接示例,然後使用標準化的數據結構進行更簡單的查詢。

SELECT 
    id, 
    CASE WHEN co1 = 'AA1' THEN co1 ELSE 0 END 
    + CASE WHEN co2 = 'AA1' THEN co2 ELSE 0 END 
    + CASE WHEN co3 = 'AA1' THEN co3 ELSE 0 END 
    + CASE WHEN co4 = 'AA1' THEN co4 ELSE 0 END 
    + etc, etc 
FROM 
    yourTable 

隨着每id 30碼,你需要30個CASE聲明。

另一種方法是每id有多行數據,而不是每id多列。

+-------+-------+-------+-------+ 
| ID | Obs | Cod | Val | 
+-------+-------+-------+-------+ 
| 01 | 1 | AA1 | 23.0 | 
| 01 | 2 | AA2 | 11.2 | 
| 01 | 3 | AA3 | 328.34| 
| 02 | 1 | AA2 | 27.0| 
| 02 | 2 | AA3 | 234.56| 
| 02 | 3 | AA4 | 23.8| 
| 03 | 1 | AA1 | 409.01| 
| 03 | 2 | AA4 | 234.98| 
+-------+-------+-------+-------+ 

的查詢是簡單的,你可以只要你喜歡不改變表結構添加儘可能多的觀察,以及一大堆的其他優點...

RDMBS您正在使用哪個
Query if one id can have several   Query if one id can only have one 
observations for the same code:   observation for any one code: 
----------------------------------   ----------------------------------- 
SELECT          SELECT 
    id,          * 
    cod,          FROM 
    SUM(val) AS val       yourTable 
FROM          WHERE 
    yourTable         cod = 'AA1' 
WHERE 
    cod = 'AA1' 
GROUP BY 
    id, 
    cod 
+0

是的,這就是爲什麼我不太喜歡有35 WHERE語句,哈哈x3 但是,我不能這樣排序,特別是有幾千條記錄=( 謝謝你的回答所有相同=) – Jerry 2012-08-06 09:51:16

+0

@ Unknown008 - 但請注意,SQL不適用於您的表結構類型。您需要預處理您的數據(請參閱您的問題的「pivot」回答)* [每次執行時可能會產生大量處理開銷] *,將您的數據標準化爲適合RDBMS/SQL *的數據[重大投資重構您的數據] *,或者有高度冗餘的代碼* [潛在的大量編碼和維護開銷] *。對不起,你似乎有一個遺留問題(數據結構),迫使你進入一個沒有「理想」方法的角落。 – MatBailie 2012-08-06 09:57:47

+0

@ Unknown008 - 另外,請注意,有很多方法可以很快地將數據降級。幾千條記錄實際上並不是很多。 – MatBailie 2012-08-06 10:01:53