2009-06-24 106 views
3

我试图在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)。

回答

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表达式中使用它。

+0

当然。我不敢相信我没有意识到把CASE放在SUM里面。谢谢! – MDStephens 2009-06-24 21:14:36

1

记住,一个GROUP BY的语句后的结果,或在一个或列使用聚合函数,具有包含其它行的总结每一行的声明。

你使用的情况下表达依赖于各行,而不是摘要值;您只能在集合函数或WHERE子句中引用非集合值(即单行值),因此解决方案将涉及将CASE放入集合函数中,在此情况下为SUM。

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 

取决于你的意思:)

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 
1

看起来很奇怪,我必须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中看到的用户不友好的分析错误。

此主题中的所有代码建议都提供了解决方案。

相关问题