【问题标题】:Each GROUP BY expression must contain at least one column that is not an outer reference每个 GROUP BY 表达式必须至少包含一个不是外部引用的列
【发布时间】:2010-12-15 18:30:34
【问题描述】:

我在这里做错了什么?我收到此错误:

SELECT LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000), 
            PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', 
            batchinfo.datapath), 8000))-1),
            qvalues.name,
            qvalues.compound,
            qvalues.rid
FROM batchinfo JOIN qvalues ON batchinfo.rowid=qvalues.rowid
WHERE LEN(datapath)>4
GROUP BY 1,2,3
HAVING rid!=MAX(rid)

我想按第一列、第二列和第三列进行分组。

没有 group by 也可以正常工作。

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    首先你不能这样做:

    having rid!=MAX(rid)
    

    HAVING 子句只能包含聚合组的属性。

    此外,1, 2, 3 在 SQL Server 的 GROUP BY 中无效 - 我认为这仅在 ORDER BY 中有效。

    你能解释一下为什么这不是你要找的吗:

    select 
    LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000), PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000))-1),
    qvalues.name,
    qvalues.compound,
    MAX(qvalues.rid)
     from batchinfo join qvalues on batchinfo.rowid=qvalues.rowid
    where LEN(datapath)>4
    group by LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000), PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000))-1),
    qvalues.name,
    qvalues.compound
    

    【讨论】:

    • @herrow 您没有 GROUP BY 摆脱,也没有在 SELECT 中使用 SUM、MIN、MAX 等聚合函数将其包围。我仍然不确定您要摆脱什么...
    【解决方案2】:

    好吧,正如之前所说,您不能通过文字 GROUP,我认为您很困惑,因为您可以通过 1、2、3 ORDER。当您使用函数作为列时,您需要通过相同的表达式进行 GROUP。此外,HAVING 子句是错误的,您只能使用聚合中的内容。在这种情况下,您的查询应该是这样的:

    SELECT 
    LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000), PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000))-1),
    qvalues.name,
    qvalues.compound,
    MAX(qvalues.rid) MaxRid
    FROM batchinfo join qvalues 
    ON batchinfo.rowid=qvalues.rowid
    WHERE LEN(datapath)>4
    GROUP BY 
    LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000), PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000))-1),
    qvalues.name,
    qvalues.compound
    

    【讨论】:

      【解决方案3】:

      您不能按文字分组,只能按列分组。

      您可能正在寻找这样的东西:

      select 
      LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000), PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000))-1) as pathinfo,
      qvalues.name,
      qvalues.compound,
      qvalues.rid
       from batchinfo join qvalues on batchinfo.rowid=qvalues.rowid
      where LEN(datapath)>4
      group by pathinfo, qvalues.name, qvalues.compound
      having rid!=MAX(rid)
      

      首先,您必须为第一个表达式指定一个列名,即as。然后你必须通过表达式指定分组中列的名称。

      【讨论】:

      • 感谢您的帮助。我只想按第一列、第二列和第三列分组。我该怎么做?
      • @herrow:您可以按第一列、第二列和第三列的名称进行分组。如果你能用自然语言解释这个查询应该做什么,可能会对我们有所帮助。
      • @dgh 我需要将其分组(左......)它是其中一列的子字符串
      【解决方案4】:

      我认为您没有正确使用 GROUP BY。

      GROUP BY 的要点是在执行数学/聚合函数之前根据某个或多个列将您的表组织成部分。

      例如,在这张表中:

      Name    Age   Salary
      Bob     25     20000
      Sally   42     40000
      John    42     90000
      

      一个 SELECT 语句可以 GROUP BY name(Bob、Sally 和 John 分别是不同的组)、Age(Bob 是一个组,Sally 和 John 是另一个)或 Salary(与 name 几乎相同的结果) .

      按“1”分组没有任何意义,因为“1”不是列名。

      【讨论】:

      • @herrow:好的,也许 GROUP BY 1 有一些我在 sql server 中不熟悉的特殊含义。但是,我仍然认为按列名分组会更接近您真正想要的。
      • 如何按第一列分组
      • 您尝试过 Cade Roux 的建议吗?例如按 LEFT(.... 分组?或者这不是“第一列”的意思?
      【解决方案5】:

      我刚刚发现了这个错误。在选择查询的 group by 子句中使用 GETDATE() [即外部引用]。

      当用相应表中的日期列替换它时,它会清除。

      想分享一个简单的例子。干杯;)

      【讨论】:

        【解决方案6】:

        当您使用 GROUP BY 时,您还需要对不在 group by 子句内的列使用聚合函数。

        我不知道你到底想做什么,但我想这会奏效:

        select 
            LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000),
            PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000))-1),
            qvalues.name,
            qvalues.compound,
            MAX(qvalues.rid)
        from
            batchinfo join qvalues on batchinfo.rowid=qvalues.rowid
        where
            LEN(datapath)>4
        group by
            LEFT(SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000),
            PATINDEX('%[^0-9]%', SUBSTRING(batchinfo.datapath, PATINDEX('%[0-9][0-9][0-9]%', batchinfo.datapath), 8000))-1),
            qvalues.name,
            qvalues.compound
        having
            rid!=MAX(rid)
        

        编辑: 我在这里要做的是一个group by,除了rid之外的所有字段。如果这不是您想要的,那么为了获得有效的 SQL 语句,您需要做的是为每个已删除的按字段分组添加聚合函数调用...

        【讨论】:

        • 是的,那是因为@Femaref 说 - 你也不能按文字分组。我将编辑我的答案。
        • @herrow: 是的,因为我保留了一个犯的错误... >:-@ 所以,“对不起”...
        【解决方案7】:

        这是一个简单的查询,用于查找药物类型为 A 且收入超过 2 的公司名称。

        SELECT CNAME 
        FROM COMPANY 
        WHERE CNO IN (
            SELECT CNO 
            FROM MEDICINE 
            WHERE type='A' 
            GROUP BY CNO HAVING COUNT(type) > 2
        )
        

        【讨论】:

        猜你喜欢
        • 2012-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-10
        • 1970-01-01
        • 1970-01-01
        • 2012-07-29
        相关资源
        最近更新 更多