【问题标题】:Cannot use Max with Count in SQL*Plus不能在 SQL*Plus 中使用 Max 和 Count
【发布时间】:2010-06-27 15:16:42
【问题描述】:

这是我的 sql 语句,我收到此错误。但是当我只使用 Max 单并且不显示其他结果时它可以工作。有人可以帮我吗

SELECT cat.CategoryName,sb.SubCategoryName,MAX((COUNT(bs.BookID))) 
FROM
  Category cat,SubCategory sb, Book_Subcategory bs 
WHERE cat.CategoryID = sb.CategoryID AND sb.SubCategoryID = bs.SubCategoryID 
GROUP BY cat.CategoryName, sb.SubCategoryName, bs.BookID;

ERROR at line 1:
ORA-00937: not a single-group group function

有人可以帮我吗?

【问题讨论】:

    标签: sql oracle aggregate-functions ora-00937


    【解决方案1】:

    SQL 不允许直接聚合聚合。

    但是,如果在 FROM 子句中的子查询中编写内部聚合(或使用 WITH 子句和公共表表达式,CTE),则可以实现结果:

    SELECT gc1.CategoryName, gc1.SubCategoryName, gc1.BookCount
      FROM (SELECT cat.CategoryName, sb.SubCategoryName,
                   COUNT(bs.BookID) AS BookCount
              FROM Category AS cat
              JOIN SubCategory AS sb ON cat.CategoryID = sb.CategoryID
              JOIN Book_Subcategory AS bs ON sb.SubCategoryID = bs.SubCategoryID
             GROUP BY cat.CategoryName, sb.SubCategoryName
           ) AS gc1
     WHERE gc1.BookCount = (SELECT MAX(gc2.BookCount)
                              FROM (SELECT cat.CategoryName, sb.SubCategoryName,
                                           COUNT(bs.BookID) AS BookCount
                                      FROM Category AS cat
                                      JOIN SubCategory AS sb
                                           ON cat.CategoryID = sb.CategoryID
                                      JOIN Book_Subcategory AS bs
                                           ON sb.SubCategoryID = bs.SubCategoryID
                                     GROUP BY cat.CategoryName, sb.SubCategoryName
                                    ) AS gc2
                            )
    

    这很复杂,因为它不使用 CTE,并且有一个必须写出两次的公用表表达式。

    使用 CTE 形式(可能有语法错误):

    WITH gc1 AS (SELECT cat.CategoryName, sb.SubCategoryName,
                        COUNT(bs.BookID) AS BookCount
                   FROM Category AS cat
                   JOIN SubCategory AS sb
                        ON cat.CategoryID = sb.CategoryID
                   JOIN Book_Subcategory AS bs
                        ON sb.SubCategoryID = bs.SubCategoryID
                  GROUP BY cat.CategoryName, sb.SubCategoryName
                )
    SELECT gc1.CategoryName, gc1.SubCategoryName, gc1.BookCount
      FROM gc1
     WHERE gc1.BookCount = SELECT MAX(gc1.BookCount) FROM gc1);
    

    更整洁!

    如果您的 DBMS 可以轻松创建临时表,则您可以使用临时表模拟 CTE。例如,IBM Informix Dynamic Server 可以使用:

    SELECT cat.CategoryName, sb.SubCategoryName,
           COUNT(bs.BookID) AS BookCount
      FROM Category AS cat
      JOIN SubCategory AS sb ON cat.CategoryID = sb.CategoryID
      JOIN Book_Subcategory AS bs ON sb.SubCategoryID = bs.SubCategoryID
     GROUP BY cat.CategoryName, sb.SubCategoryName
      INTO TEMP gc1;
    
    SELECT gc1.CategoryName, gc1.SubCategoryName, gc1.BookCount
      FROM gc1
     WHERE gc1.BookCount = (SELECT MAX(gc1.BookCount) FROM gc1);
    
    DROP TABLE gc1;  -- Optional: table will be deleted at end of session anyway
    

    鉴于以下表格和数据,在 MacOS X 10.6.4 上针对 IBM Informix Dynamic Server 11.50.FC6 运行时,主查询(从该答案复制和粘贴)给出了我预期的结果,即:

    Non-Fiction    SQL Theory    4
    Fiction        War           4
    

    这并不能证明它在针对 Oracle 运行时“必须工作” - 我没有 Oracle,也无法演示任何一种方式。它确实表明至少有一个 SQL DBMS 可以毫无问题地处理查询。 (由于 IDS 不支持 WITH 子句和 CTE,我无法证明该公式是否有效。)

    架构

    CREATE TABLE Category
    (
        CategoryID INTEGER NOT NULL PRIMARY KEY,
        CategoryName VARCHAR(20) NOT NULL
    );
    CREATE TABLE SubCategory
    (
        CategoryID INTEGER NOT NULL REFERENCES Category,
        SubCategoryID INTEGER NOT NULL PRIMARY KEY,
        SubCategoryName VARCHAR(20) NOT NULL
     );
    CREATE TABLE Book_SubCategory
    (
        SubCategoryID INTEGER NOT NULL REFERENCES SubCategory,
        BookID INTEGER NOT NULL PRIMARY KEY
    );
    

    数据

    INSERT INTO Category VALUES(1, 'Fiction');
    INSERT INTO Category VALUES(2, 'Non-Fiction');
    
    INSERT INTO SubCategory VALUES(2, 1, 'SQL Theory');
    INSERT INTO SubCategory VALUES(2, 2, 'Mathematics');
    INSERT INTO SubCategory VALUES(1, 3, 'Romance');
    INSERT INTO SubCategory VALUES(1, 4, 'War');
    
    INSERT INTO Book_SubCategory VALUES(1, 10);
    INSERT INTO Book_SubCategory VALUES(2, 11);
    INSERT INTO Book_SubCategory VALUES(3, 12);
    INSERT INTO Book_SubCategory VALUES(3, 13);
    INSERT INTO Book_SubCategory VALUES(4, 14);
    INSERT INTO Book_SubCategory VALUES(1, 15);
    INSERT INTO Book_SubCategory VALUES(1, 16);
    INSERT INTO Book_SubCategory VALUES(2, 17);
    INSERT INTO Book_SubCategory VALUES(1, 18);
    INSERT INTO Book_SubCategory VALUES(3, 19);
    INSERT INTO Book_SubCategory VALUES(4, 20);
    INSERT INTO Book_SubCategory VALUES(4, 21);
    INSERT INTO Book_SubCategory VALUES(4, 22);
    

    【讨论】:

    • 任何简单的方法来实现这样的 sql 语句,而不是这样复杂。另一件事是在你给我的第一个代码中存在一些问题。我试着检查它。但给我错误说因为 GC1 没有正确结束。我在 Oracle 中使用 SQLPLUS。
    • FWIW:自从写了这个答案后,我了解到 Oracle 不遵循 SQL 标准,并且在创建表别名时不允许 AS。因此,您必须在 Oracle 中编写 FROM Category Cat 而不是 FROM Category AS Cat(但大多数其他 DBMS 都允许该 AS)。
    【解决方案2】:

    我认为错误出在 GROUP BY 子句中(bs.BookID 不属于那里):

    SELECT cat.CategoryName,sb.SubCategoryName,MAX(COUNT(bs.BookID)) 
    FROM Category cat,SubCategory sb, Book_Subcategory bs 
    WHERE cat.CategoryID =sb.CategoryID AND sb.SubCategoryID=bs.SubCategoryID 
    GROUP BY cat.CategoryName,sb.SubCategoryName;
    

    顺便说一句,空格(和标点符号)是你的朋友。不要偷懒。

    【讨论】:

      猜你喜欢
      • 2014-05-26
      • 1970-01-01
      • 2016-12-02
      • 1970-01-01
      • 1970-01-01
      • 2016-04-17
      • 2012-03-04
      • 2021-09-11
      • 1970-01-01
      相关资源
      最近更新 更多