为什么必须对 CASE 语句中的列进行 GROUP BY?

发布于 2024-07-24 23:15:09 字数 1181 浏览 10 评论 0原文

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

对我来说,我必须 GROUP 似乎很奇怪BY Qty 和 MarkedUpTotal 当它们仅由 CASE 语句有条件地使用时。 如果我删除最后一个选择(CASE 语句),查询将正常执行,并且不需要数量或价格位于 GROUP BY 中。

为什么 SQL 需要这个? 是否有一个查询可以完成上述任务?

目前我正在通过使用临时表来解决该问题。 如果需要,我会修改每个条目的 MarkedUpTotal,然后在临时表的主查询中执行简单的 SUM(MarkedUpTotal)。

I'm trying to run a query in SQL Server 2008 against a table where some of the data was entered inconsistently and I have to handle this.

Table data example:

OrderID   Qty   Price   MarkedUpTotal
1         10    1.00    11.00
1         -1    1.00    -1.10
1         -1    1.00    1.10

I have to handle the situation where the Qty is negative but the MarkedUpTotal was entered as positive.

I'd like to run the following query:

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

However, I get the following error when I run this query:

Column Qty is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Column MarkedUpTotal is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

I desire the following result:

OrderID    OrderTotalQty   InternalCost   ClientCost
1          8               8.00           8.80

It seems odd to me that I must GROUP BY Qty and MarkedUpTotal when they are only being used conditionally by the CASE statement. If I remove the last selection (the CASE statement) the query executes fine and does not require Qty or Price to be in the GROUP BY.

Why does SQL require this? Is there a single query that could accomplish the above?

Currently I'm resolving the issue by using a temp table. I modify each entry's MarkedUpTotal if needed and then do a simple SUM(MarkedUpTotal) in the main query from the temp table.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

寻梦旅人 2024-07-31 23:15:09
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 表达式中使用它。

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

The reason it gives error is because, you are SUMming it up inside the CASE - which will return 1 value outside. To the SELECT with GROUP BY, it will look like you are passing in a numeric value (which could be a constant or comes from some other source) as a column.

Think of your SQL Statement, similar to this

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

Now this is returning a new column (ClientCost), which is not using any aggregation.
So, it asks you to use that in GROUP BY expression.

妳是的陽光 2024-07-31 23:15:09

请记住,GROUP BY 语句的结果,或者其中一个或多个列使用聚合函数的语句的结果,每一行都包含其他行的摘要。

您使用的 CASE 表达式取决于各个行的值而不是摘要; 您只能在聚合函数或 WHERE 子句中引用非聚合值(即单行值),因此解决方案将涉及将 CASE 放入聚合函数中,在本例中为 SUM。

Bear in mind that the result of a GROUP BY statement, or of a statement where one or columns uses an aggregate function, has each row containing a summary of other rows.

The CASE expression you're using is dependent on values of individual rows rather than summaries; you may only reference non-aggregate values (i.e. single-row values) in an aggregate function, or in the WHERE clause, so the solution would involve placing your CASE inside an aggregate function, in this case your SUM.

葮薆情 2024-07-31 23:15:09

错误是关于这部分的。 Sql Server 应使用什么数量行值?

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

取决于您的意思:)

The error is about this part. What Qty row value should Sql Server use?

CASE WHEN Qty < 0 and MarkedUpTotal > 0 
    THEN sum(-1*MarkedUpTotal) 
    ELSE SUM(MarkedUpTotal) 
END as ClientCost

You could rewrite it like:

sum(CASE WHEN Qty < 0 and MarkedUpTotal > 0 
    THEN sum(-1*MarkedUpTotal) 
    ELSE SUM(MarkedUpTotal) 
END as ClientCost)

Or:

CASE WHEN sum(Qty) < 0 and sum(MarkedUpTotal) > 0 
    THEN sum(-1*MarkedUpTotal) 
    ELSE SUM(MarkedUpTotal) 
END as ClientCost

Depending on what you mean :)

彩虹直至黑白 2024-07-31 23:15:09

像这样做:

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

Do it like this:

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
七秒鱼° 2024-07-31 23:15:09

我觉得很奇怪,我必须分组
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 Server 不知道如何评估 CASE WHEN Qty 0 且 MarkedUpTotal > 0 。 表中的这些记录有 3 个不同的值,这通常不是问题 - 但由于您正在对记录进行分组,因此该表达式毫无意义,因为 SQL Server 不知道在计算时使用这三个值中的哪一个case 表达式,因此它会抛出 OP 中看到的用户不友好的解析错误。

该线程中的所有代码建议都提供了解决方案。

It seems odd to me that I must GROUP
BY Qty and MarkedUpTotal when they are
only being used conditionally by the
CASE statement.

I've highlighted the error below:

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 server doesn't know how to evaluate CASE WHEN Qty < 0 and MarkedUpTotal > 0. You have 3 different values for these records in your table, which is normally not a problem -- but since you're grouping your records, the expression is meaningless since SQL server doesn't know which of the three values to use when it evaluates the case expression, so it throws the user-unfriendly parse errors seen in the OP.

All of the code suggestions in this thread provide a solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文