使用 GROUP BY 从多个表中选择

Posted

技术标签:

【中文标题】使用 GROUP BY 从多个表中选择【英文标题】:SELECT from multiple tables with GROUP BY 【发布时间】:2012-09-16 13:49:40 【问题描述】:

我在多表查询方面遇到了一点问题。 (RDBMS:访问)

这是数据库模式:(此查询中仅使用 S_Cards、Books、Authors、Students 表) S_Cards 是学生书单(在图书馆)。

查询: 选择学生中最受欢迎的作者以及该作者在图书馆订购的书籍的数量。

虽然我可以在一个查询中得到这样的订单+作者列表:

SELECT 
    Students.FirstName & " " & Students.LastName AS [Student], 
    Books.Name AS [Book], Authors.FirstName & " " & Authors.LastName AS [Author]
FROM 
    Students, 
    Books, 
    S_Cards, 
    Authors
WHERE 
    S_Cards.ID_Student = Students.ID 
AND S_Cards.ID_Book = Books.ID 
AND Books.ID_Author = Authors.ID
ORDER BY Authors.LastName

结果(抱歉,是俄语):

我不明白,为什么我不能像这样 COUNT 和 GROUP BY:

SELECT 
    Students.FirstName & " " & Students.LastName AS [Student], 
    Books.Name AS [Book], 
    COUNT(Authors.FirstName & " " & Authors.LastName) AS [Number of books]
FROM Students, Books, S_Cards, Authors
WHERE 
    S_Cards.ID_Student = Students.ID 
AND S_Cards.ID_Book = Books.ID 
AND Books.ID_Author = Authors.ID
GROUP BY 3

我收到一条错误消息,“Authors.FirstName & " " & Authors.LastName' 不是静态函数或组的一部分。

问题:

    有没有办法在没有 JOIN 的情况下执行此查询,仅通过 GROUP BY、SELECT、UNION 以及如何执行? 我的第二个查询有什么问题?

【问题讨论】:

【参考方案1】:

解决方案(摘自older revision in question):

SELECT TOP 1 Author, COUNT(Book) AS [Number of books] FROM
(
    SELECT 
        Students.FirstName & " " & Students.LastName AS [Student], 
        Books.Name AS [Book], 
        Authors.FirstName & " " & Authors.LastName AS [Author]
    FROM 
        Students, 
        Books, 
        S_Cards, 
        Authors
    WHERE 
        S_Cards.ID_Student = Students.ID AND
        S_Cards.ID_Book = Books.ID AND
        Books.ID_Author = Authors.ID
    ORDER BY Authors.LastName
)
GROUP BY Author
ORDER BY 2 DESC

【讨论】:

【参考方案2】:

SQL Server 中的字符串concatenation operator 是+ 而不是&。此外,您应该按聚合函数的事物进行分组。

SELECT Students.FirstName + ' ' + Students.LastName AS [Student]
     , Books.Name AS [Book]
     , COUNT(Authors.FirstName + ' ' + Authors.LastName) AS [Number of books]
  FROM Students
  JOIN S_Cards
    ON S_Cards.ID_Student = Students.ID
  JOIN BOOKS
    ON S_Cards.ID_Book = Books.ID 
  JOIN Authors
    ON Books.ID_Author = Authors.ID
 GROUP BY Students.FirstName + ' ' + Students.LastName
        , Books.Name

请注意,我已将您的查询更改为标准的 ANSI 连接语法,这使得错误更难产生并且更易于阅读。

仔细想想,你的计数似乎有点奇怪。书的数量不是COUNT(Books.ID)吗?

【讨论】:

假设您正在使用 SQL Server(看起来很像)。以后请始终使用适当的 RDBMS 标记问题。 感谢您的回复。我认为 COUNT(Books.ID) 会计算订购某本书的次数。我需要计算作者的任何书被订购了多少次,而不是特定的书。 RDBMS 是 Access。【参考方案3】:

您必须对不属于聚合函数的任何内容进行 GROUP BY:

SELECT 
    Students.FirstName & " " & Students.LastName AS [Student], 
    Books.Name AS [Book], 
    COUNT(Authors.FirstName & " " & Authors.LastName) AS [Number of books]
FROM Students, Books, S_Cards, Authors
WHERE 
    S_Cards.ID_Student = Students.ID 
AND S_Cards.ID_Book = Books.ID 
AND Books.ID_Author = Authors.ID
GROUP BY Students.FirstName & " " & Students.LastName, 
    Books.Name AS [Book]

我建议您开始使用显式而不是隐式连接。在大多数情况下,MS Access 有更好的选择。

<...>
FROM Students
INNER JOIN S_Cards
ON Students.ID = S_Cards.ID_Student

或者

<...>
FROM Students
LEFT JOIN S_Cards
ON Students.ID = S_Cards.ID_Student

查询设计窗口将允许您使用正确的语法构建您的 JOIN。只需将连接字段从一个表拖放到下一个表,然后选择您需要的连接类型。

【讨论】:

以上是关于使用 GROUP BY 从多个表中选择的主要内容,如果未能解决你的问题,请参考以下文章

如何从表中选择带有 oracle sql 中的 group by 子句的嵌套 json 对象?

如何通过内部连接使用 group by

使用 GROUP BY,选择每个组中 ID 最低的记录 ID

如何在 SQL 中连接多个表和 GROUP BY

如何使用 group by(基于一列)从表中选择多列,在 hive 查询中具有和计数

从 GROUP BY 组中选择具有特定内容的行