问题
I'm trying to find the sum of specific values within a table, using SQL. A sample table is:
+-------+-------+-------+-------+-------+-------+-------+
| 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 |
+-------+-------+-------+-------+-------+-------+-------+
I have 35 such 'Code' columns and values.
What I need is selecting a table having only one code. Say I need Code AA3, this would be (the Code column is not required here, but only to show where I got the values):
+-------+-------+--------+
| ID | Code | Value |
+-------+-------+--------+
| 01 | AA3 | 328.34|
| 02 | AA3 | 234.56|
| 03 | AA3 | 0|
+-------+-------+--------+
And I will later need another (separate) query which contains the sum of several codes, for example the sum of codes AA1 and AA2 together.
+-------+---------+
| ID | Value |
+-------+---------+
| 01 | 34.2|
| 02 | 27.0|
| 03 | 409.01|
+-------+---------+
I was thinking about having a 'WHERE' and run on every 35 columns, but that would really be tedious and this does not seem too efficient. I was wondering if there was a way to do that through SQL (I can do it with Excel with an if statement and it works wonders).
Maybe if there was a way to 'search' through a row, return the column name and then use that column name to retrieve the number?
Let me know if you require more information =)
回答1:
What you should do is store your data in a normalised form.
However...
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
will return the results you seek
回答2:
Your table structure is less than ideal. I'll show you a straight forward example similar to your Excel based IF
method, and then a much simpler query with a normalised data-structure.
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
With 30 codes per id
, you need 30 CASE
statements.
The alternative is to have several rows of data per id
, instead of several columns per 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|
+-------+-------+-------+-------+
The the query is simple, you can add as many observations as you like without changing the table structure, and a whole host of other advantages...
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
来源:https://stackoverflow.com/questions/11825158/sum-of-specific-values-in-sql