我正在尝试在SQL Server 2008中针对某些数据输入不一致的表运行查询,我必须处理此问题。
表数据示例:
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子句中。
列MarkedUpTotal在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。
我希望得到以下结果:
OrderID OrderTotalQty InternalCost ClientCost
1 8 8.00 8.80
对于我来说,当CASE语句有条件地使用它时,我必须使用GROUP BY Qty和MarkedUpTotal。如果我删除最后一个选择(CASE语句),则查询执行正常,并且不要求数量或价格在GROUP BY中。
为什么SQL需要这个?是否有一个查询可以完成上述操作?
目前我正在使用临时表来解决问题。如果需要,我修改每个条目的MarkedUpTotal,然后在临时表的主查询中做一个简单的SUM(MarkedUpTotal)。
答案 0 :(得分:13)
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表达式中使用它。
答案 1 :(得分:1)
请记住,GROUP BY语句或一个或多个列使用聚合函数的语句的结果,每行包含其他行的摘要。
您使用的CASE表达式取决于各行的值而不是摘要;您只能在聚合函数或WHERE子句中引用非聚合值(即单行值),因此解决方案将涉及将CASE放在聚合函数中,在本例中为SUM。
答案 2 :(得分:1)
错误与此部分有关。 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
取决于您的意思:))
答案 3 :(得分:1)
这样做:
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
答案 4 :(得分:1)
对我而言,我必须是GROUP BY Qty和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
。表中的这些记录有3个不同的值,这通常不是问题 - 但是由于您对记录进行分组,因此表达式没有意义,因为SQL服务器在评估时不知道要使用哪三个值case表达式,因此它会抛出OP中看到的用户不友好的解析错误。
此主题中的所有代码建议都提供了解决方案。