跨列和行求和
Posted
技术标签:
【中文标题】跨列和行求和【英文标题】:Sum across columns and rows 【发布时间】:2015-02-27 08:35:12 【问题描述】:考虑这样的表格
table
+--------+---------+-----------+---------+-----------+
| BookId | ItemId1 | Quantity1 | ItemId2 | Quantity2 |
+--------+---------+-----------+---------+-----------+
| 1 | 1 | 2 | 2 | 1 |
| 1 | 3 | 1 | 2 | 1 |
| 2 | 1 | 1 | 2 | 1 |
+--------+---------+-----------+---------+-----------+
现在我想获取按书籍分组的每个项目的列数量总和。那么我怎样才能在不同的列中求和呢?现在我使用一种尴尬的解决方案,比如构建一个临时表,然后查询这个,但它必须以更优雅的方式实现!?
select
BookId 'BookId',
ItemId1 'ItemId',
Quantity1 'Quantity'
into #temptab
from table
union all
select
BookId,
ItemId2,
Quantity2
from table
然后
select
BookId,
ItemId,
sum(Quantity)
from #temptab
group by ItemId, BookId
我怎样才能摆脱这个中间步骤?
期望的输出:
+--------+--------+----------+
| BookId | ItemId | Quantity |
+--------+--------+----------+
| 1 | 1 | 2 |
| 1 | 3 | 1 |
| 1 | 2 | 2 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
+--------+--------+----------+
【问题讨论】:
如果 ItemId1 与 ItemId2 匹配,是否要将它们相加? 使用 UNPIVOT 命令。 您应该设计数据模型以反映数据,而不是电子表格或某种物理形式。有重复的列组通常是一个不好的迹象。ItemId1
和 ItemId2
有什么本质上的不同吗?如果是这样,为什么您现在要针对此查询对它们进行相同的处理?如果没有,为什么表中不只有一个 ItemId
和 Quantity
列和更多行?
@ Damien_The_Unbeliever 原则上你是对的。但是,这是我无法更改且没有影响的数据结构
【参考方案1】:
使用cross apply
和table valued constructor
到unpivot
数据,然后根据bookid
和item
查找sum
。
这将避免您的中间步骤
SELECT BookId,
item,
Sum(quantity)
FROM Youratble
CROSS apply (VALUES(Quantity1,ItemId1),
(Quantity2,ItemId2))cs(quantity, item)
GROUP BY BookId,
item
正如 Mikael Eriksson 提到的 sql server 2005
使用这个
SELECT BookId,
item,
Sum(quantity)
FROM Youratble
cross apply
(select Quantity1, ItemId1
union all
select Quantity2, ItemId2) as cs(quantity, item)
GROUP BY BookId,
item
【讨论】:
我搞砸了,把 bookId 放在我的交叉申请中。删除了我的解决方案和 + 1 谢谢。但是,我收到错误“关键字‘值’附近的语法不正确。”似乎表值构造函数仅在 SQL Server 2008 中创建,我使用的是 2005。您也有解决方案吗? @WilliFischer 改为使用 union allcross apply (select Quantity1, ItemId1 union all Quantity2, ItemId2) as cs(quantity, item)
@ Mikael Eriksson 但是我再次使用了我想避免的子查询。
@WilliFischer - 已更新。仅供参考,这不是子查询。【参考方案2】:
根据您所做的,您可以使用子查询一步完成:
select
combined.BookId,
combined.ItemId,
sum(combined.Quantity)
from
(select
BookId 'BookId',
ItemId1 'ItemId',
Quantity1 'Quantity'
from tableName
union all
select
BookId,
ItemId2,
Quantity2
from tableName) as combined
group by combined.ItemId, combined.BookId
【讨论】:
我想避免子查询。还是谢谢以上是关于跨列和行求和的主要内容,如果未能解决你的问题,请参考以下文章