【问题标题】:列“不包含在聚合函数或 GROUP BY 子句中”
【发布时间】:2022-01-14 00:25:33
【问题描述】:

查询:

SELECT 
    A.mrno, A.remarks, 
    B.itemcode, B.description, B.uom, B.quantity, 
    C.whsecode, MAX(C.quantity) AS whseqty, D.rate 
FROM 
    Mrhdr A
INNER JOIN 
    Mrdtls B ON A.mrno = B.mrno
INNER JOIN 
    inventoryTable C ON B.itemcode = C.itemcode
INNER JOIN 
    Items D ON B.itemcode = D.itemcode
WHERE 
    (A.mrno = @MRNo AND B.quantity < C.quantity);

错误:

列“Mrhdr.mrno”在选择列表中无效,因为它不是 包含在聚合函数或 GROUP BY 子句中。

它表示mrno 列不包含在某个东西的聚合函数中,但是当我对它做一些事情时,比如将它放在一个GROUP BY 子句中,下一个列请求返回相同的错误,直到除@ 之外的最后一列987654324@ 列,并且当它们都在 GROUP BY 子句中时,它只会返回相同的输出,而不返回数量的最高或最大值。当我使用 MAX 或聚合函数时,我应该如何处理其他列。

上面查询的输出:

如果我将所有列放在 GROUP BY 子句中,它会返回带有两个 itemcode FG 4751 的输出,它只是删除聚合函数的错误,但我只想返回最高值(仅 100 ,仓库/库存中的最高数量)。

【问题讨论】:

  • 通常,如果您将某些列放在聚合函数下,那么所有其他列必须在聚合函数下或在“分组依据”子句中列出
  • 请告诉我们查询应该做什么。到目前为止,您似乎想要显示数量小于产品总库存的所有 Mrdtls(可能是订单详细信息?)。因此,对于库存 10 + 10 = 20 和订单 10、15、20 和 25 的产品,您将只显示订单 10 和 15。这是您希望查询执行的操作吗?
  • 您的 DBMS 是什么?请用它标记请求。 SQL 标准可能只需要 GROUP BY b.id 就可以了,而其他一些 DBMS 可能需要在该子句中添加额外的列。始终使用您正在使用的 DBMS 标记 SQL 请求。
  • @ThorstenKettner 我添加了它返回的输出和查询应该执行的输出。发的时候忘记加了,希望对你有帮助。

标签: sql group-by max aggregate-functions


【解决方案1】:

您希望处理每个产品的最大库存数量。但是您要加入所有库存行,您应该只选择最大数量的行。

这可以通过横向连接来完成,如果您的 DBMS 支持此功能(您忘记告诉我们您使用的是哪个),或者只是通过应用如下窗口函数来连接相关行。

SELECT 
    A.mrno, A.remarks, 
    B.itemcode, B.description, B.uom, B.quantity, 
    C.whsecode, C.whseqty, D.rate 
FROM 
    Mrhdr A
INNER JOIN 
    Mrdtls B ON A.mrno = B.mrno
INNER JOIN 
(
    SELECT
      itemcode, whsecode, quantity as whseqty,
      MAX(quantity) OVER (PARTITION BY itemcode) AS max_qty
    FROM inventoryTable
) C ON B.itemcode = C.itemcode AND C.whseqty = C.max_qty
INNER JOIN 
    Items D ON B.itemcode = D.itemcode
WHERE 
    A.mrno = @MRNo AND B.quantity < C.whseqty;

这个查询应该可以在大多数 DBMS 中使用。如果您正在使用支持标准 SQL FETCH WITH TIES 子句的 DBMS,我会将连接更改为:

INNER JOIN 
(
    SELECT itemcode, whsecode, quantity as whseqty
    FROM inventoryTable
    ORDER BY RANK() OVER (PARTITION BY itemcode ORDER BY quantity DESC)
    FETCH FIRST ROW WITH TIES
) C ON B.itemcode = C.itemcode

以便只选择子查询中的顶行,而不是稍后笨拙地过滤它们。但是,横向连接在这里甚至可以被认为更直接。

【讨论】:

  • whsecode返回错误,因为它不在C的SELECT语句内
  • @Richard Johnson:感谢您指出这一点。我错过了那部分。所以我们不能聚合,而是必须选择行。我已经相应地更新了我的答案。
【解决方案2】:

将所有内容放在 group by 子句中的替代方法是使用窗口函数。那么问题就变成了MAX值相对于什么?

例如,您可以根据所有条件获取 MAX 值,这将返回类似的结果以分组依据,而不会只为列留下不同的值。

SELECT 
    A.mrno, 
    A.remarks, 
    B.itemcode, 
    B.description, 
    B.uom, 
    B.quantity, 
    C.whsecode, 
    MAX(C.quantity) OVER(PARTITION BY A.mrno, A.remarks, B.itemcode, B.description, B.uom, B.quantity, C.whsecode, D.rate) AS whseqty, 
    D.rate 
FROM 
    Mrhdr A
INNER JOIN 
    Mrdtls B ON A.mrno = B.mrno
INNER JOIN 
    inventoryTable C ON B.itemcode = C.itemcode
INNER JOIN 
    Items D ON B.itemcode = D.itemcode
WHERE 
    (A.mrno = @MRNo AND B.quantity < C.quantity);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    相关资源
    最近更新 更多