【问题标题】:Sum of specific values in SQLSQL 中特定值的总和
【发布时间】:2012-08-06 08:54:30
【问题描述】:

我正在尝试使用 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|
+-------+---------+

我正在考虑创建一个“WHERE”并在每 35 列上运行一次,但这确实很乏味,而且似乎效率也不高。我想知道是否有办法通过 SQL 来做到这一点(我可以用 Excel 和 if 语句来做到这一点,而且效果很好)。

也许有办法“搜索”一行,返回列名,然后使用该列名检索数字?

如果您需要更多信息,请告诉我 =)

【问题讨论】:

  • 您使用的是哪个 RDMBS,SQL Server、Oracle、MySQL?在您说“使用 SQL”的第一句话中,您的意思是 MS SQL Server?关于最后一个问题,您是否只有 3 个代码列? SUM 仅适用于 AA1 和 AA2 或更多组合?
  • 啊,是的,我的错。我使用的是 SQL Server 2008R2。
  • 出于某种原因,我没有看到您的其他评论...哦,好吧。是的,实际上有 35 个代码列和 35 个金额列。代码从 AA1 到 AA652 不等。而对于第二部分(添加几个代码),我需要添加 9 个代码:AA74、AA76、AA78 等等。

标签: sql sql-server-2008-r2 sum rows multiple-columns


【解决方案1】:

您应该做的是以标准化形式存储您的数据

不过……

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

将返回您寻求的结果

【讨论】:

  • 我希望它被标准化! >.
  • UNPIVOT 采用像您这样的非规范化表,并将其规范化(即:使其更垂直和更少水平)。然而它只能做一种数据类型,所以你需要做两次才能把两种类型都拿出来。 RIGHT 将文本数据 (CO1, CO2) 的最后一个字符与数值数据 (VA1, VA2) 的最后一个字符相匹配。尝试将 SUM(V) 替换为 * 以查看整个数据集
  • 啊!我以为您正在获取列值中的值并获取最后一个字符!通过选择我现在理解的所有内容,它实际上是您匹配的列名。谢谢!这样可行! :D (除了我在 SQL Server 中导入的列数据类型不匹配...哦,我得重新正确导入它们)
  • @Unknown008:如果您自己导入数据,您不能在该步骤中对其进行标准化吗?可能会为您省去很多麻烦。
  • 啊,直到现在才注意到你的评论,抱歉回复晚了。不,我得到了这样的数据。我希望我以后不会得到更多这样的数据。
【解决方案2】:

您的表结构不太理想。我将向您展示一个类似于基于 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|
+-------+-------+-------+-------+ 

查询很简单,您可以在不更改表结构的情况下添加任意数量的观察结果,还有许多其他优点...

 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

【讨论】:

  • 是的,这就是为什么我不太热衷于拥有 35 个 WHERE 语句,哈哈 x3 但是不,我不能这样排序,尤其是有几千条记录 =( 谢谢你的答案都一样=)
  • @Unknown008 - 但是请注意,SQL 不适用于您的表结构类型。您要么需要预处理您的数据(请参阅pivot 对您的问题的回答)[每次执行的处理开销可能很大],将您的数据标准化为适合 RDBMS/SQL 的数据[大量投资重构您的数据],或具有高度冗余的代码[潜在的大量编码和维护开销]。抱歉,您似乎有一个遗留问题(数据结构),迫使您陷入没有“理想”方法的角落。
  • @Unknown008 - 另外,请注意有很多方法可以非常快速地规范化您的数据。几千条记录实际上并不多。
  • 我明白了,感谢 cmets Dems =) 我们实际上是要求下次对数据进行更多排序;每个代码都有一列,这应该通过简单的SELECT SUM(column) FROM table GROUP BY id 使事情变得更容易。我想这次我们会坚持到卓越。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2016-10-25
  • 2016-07-08
  • 2016-02-10
  • 2020-03-21
  • 1970-01-01
  • 2022-10-13
相关资源
最近更新 更多