为什么必须GROUP BY CASE语句中的列?
我试图在SQL Server 2008中针对某个数据输入不一致的表中运行查询,并且必须处理此问题。为什么必须GROUP BY CASE语句中的列?
表数据例如:
OrderID Qty Price MarkedUpTotal
1 10 1.00 11.00
1 -1 1.00 -1.10
1 -1 1.00 1.10
我必须处理情况的数量是负的,但MarkedUpTotal被输入为阳性。
我想运行下面的查询:
SELECT OrderID, SUM(Qty) as OrderTotalQty,
SUM(Qty*Price) as InternalCost,
CASE WHEN Qty < 0 and MarkedUpTotal > 0
THEN sum(-1*MarkedUpTotal)
ELSE SUM(MarkedUpTotal) END as ClientCost
FROM OrderItems
GROUP BY OrderID
不过,我得到以下错误,当我运行此查询:
列数量是因为它是在选择列表中无效不包含在聚合函数或GROUP BY子句中。
Column MarkedUpTotal在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。
我想要的结果如下:
OrderID OrderTotalQty InternalCost ClientCost
1 8 8.00 8.80
这似乎很奇怪,我认为我必须当他们只被有条件通过CASE语句中使用GROUP BY数量和MarkedUpTotal。如果我删除最后一个选择(CASE语句),则查询执行正常,并且不要求数量或价格在GROUP BY中。
为什么SQL需要这个?有没有可以完成上述的单个查询?
目前我正在通过使用临时表来解决问题。如果需要,我修改每个条目的MarkedUpTotal,然后在临时表的主查询中执行一个简单的SUM(MarkedUpTotal)。
SELECT OrderID, SUM(Qty) as OrderTotalQty,
SUM(Qty*Price) as InternalCost,
SUM(CASE WHEN Qty < 0 and MarkedUpTotal > 0
THEN -1*MarkedUpTotal
ELSE MarkedUpTotal) END as ClientCost
FROM OrderItems
GROUP BY OrderID
它给出错误的原因是因为,你在CASE中合计 - 它会在外部返回1个值。对于使用GROUP BY的SELECT,它将看起来像您正在将数值(可能是常量或来自其他来源)作为列传递。
认为你的SQL语句中,类似这样的
SELECT OrderID, SUM(Qty) as OrderTotalQty,
SUM(Qty*Price) as InternalCost,
CASE WHEN Qty < 0 and MarkedUpTotal > 0
THEN 10
ELSE 20 END as ClientCost
FROM OrderItems
GROUP BY OrderID
现在这个函数返回一个新列(ClientCost),这是不使用任何聚集。
因此,它要求你在GROUP BY表达式中使用它。
记住,一个GROUP BY的语句后的结果,或在一个或列使用聚合函数,具有包含其它行的总结每一行的声明。
你使用的情况下表达依赖于各行,而不是摘要值;您只能在集合函数或WHERE子句中引用非集合值(即单行值),因此解决方案将涉及将CASE放入集合函数中,在此情况下为SUM。
错误与此部分有关。 Sql Server使用什么Qty行值?
CASE WHEN Qty < 0 and MarkedUpTotal > 0
THEN sum(-1*MarkedUpTotal)
ELSE SUM(MarkedUpTotal)
END as ClientCost
你可以重写它想:
sum(CASE WHEN Qty < 0 and MarkedUpTotal > 0
THEN sum(-1*MarkedUpTotal)
ELSE SUM(MarkedUpTotal)
END as ClientCost)
或者:
CASE WHEN sum(Qty) < 0 and sum(MarkedUpTotal) > 0
THEN sum(-1*MarkedUpTotal)
ELSE SUM(MarkedUpTotal)
END as ClientCost
取决于你的意思:)
做这样的:
SELECT OrderID, SUM(Qty) as OrderTotalQty,
SUM(Qty*Price) as InternalCost,
sum(CASE WHEN Qty < 0 and MarkedUpTotal > 0
THEN -1*MarkedUpTotal
ELSE MarkedUpTotal END) as ClientCost
FROM OrderItems
GROUP BY OrderID
看起来很奇怪,我必须GROUP BY数量和MarkedUpTotal当它们是 只有条件使用 CASE语句。
我突出以下错误:
SELECT OrderID, SUM(Qty) as OrderTotalQty,
SUM(Qty*Price) as InternalCost,
CASE WHEN Qty < 0 and MarkedUpTotal > 0 -- BOOM!!!!!!
THEN sum(-1*MarkedUpTotal)
ELSE SUM(MarkedUpTotal) END as ClientCost
FROM OrderItems
GROUP BY OrderID
SQL服务器不知道如何评价CASE WHEN Qty < 0 and MarkedUpTotal > 0
。在表中这些记录有三种不同的值,这通常不是问题 - 但由于您正在对记录进行分组,因此表达式没有意义,因为SQL Server在计算时不知道要使用三个值中的哪一个case表达式,所以它引发了在OP中看到的用户不友好的分析错误。
此主题中的所有代码建议都提供了解决方案。
当然。我不敢相信我没有意识到把CASE放在SUM里面。谢谢! – MDStephens 2009-06-24 21:14:36