sql GROUP BY和HAVING不工作

时间:2016-12-06 09:50:20

标签: mysql sql

我有这个SQL查询,它给我一个不完整的结果(一半结果)。我想要从学生表中检索同一班级的所有学生信息,然后按班级分组。

这些是查询代码:

SELECT first_name, last_name, username 
FROM students 
GROUP BY class        
HAVING class IN(SS3);

SELECT first_name, last_name, class 
FROM students 
GROUP BY class
HAVING class = 'JSS1';

SELECT user_id, first_name, last_name, class, COUNT(*) AS total_students
FROM students 
GROUP BY class
HAVING class IN ('JSS1')

最后一个查询也只显示一个信息,这是第一个" jss1"表中的班级学生姓名,但这次显示有17名学生在jss1

如何操纵查询以显示同一班级中学生的所有姓名?

这是表结构:

CREATE TABLE IF NOT EXISTS `students` (
    `user_id` int(11) NOT NULL AUTO_INCREMENT,
    `class` varchar(10) NOT NULL,
    `first_name` varchar(30) NOT NULL,
    `last_name` varchar(50) NOT NULL,
    `username` varchar(20) NOT NULL,
    PRIMARY KEY (`user_id`)
)

4 个答案:

答案 0 :(得分:1)

您编写的查询没有任何意义,也不会解析我知道的任何其他DBMS。 MySQL extends the standard SQL use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause.,既可以是祝福也可以是诅咒。

要提供帮助,请考虑以下示例数据

UserID      Class       First_name  
------------------------------------
1           A           Test 1  
2           A           Test 2  
3           B           Test 3  
4           B           Test 4  
5           C           Test 5  

现在,在您的第一个查询中(调整为适合上述数据)

SELECT first_name
FROM students 
GROUP BY class        
HAVING class IN('A');

我们首先需要考虑上述操作的逻辑顺序:

1. FROM
2. WHERE
3. GROUP BY
4. HAVING 
5. SELECT

所以首先要看的是group by,因为class是分组列,你想要为每个组返回一行,所以你会得到:

class  first_name
------------------
A       ???
B       ???
C       ???

现在有条款规定它必须是A,留下:

class  first_name
------------------
A       ???

现在,这就是大多数DBMS失败的原因,此时您需要SELECT first_name您有两个可用值("测试1"和& #34;测试2")但只有一行要填充,并且已经给出引擎没有关于两者中哪一个选择的说明。文档说明引擎可以自由选择任何可用值,并且该顺序不会对其产生影响,因此根据执行计划,您可能会对同一查询有所不同。

虽然您对GROUP BY不太确定,但我建议您启用ONLY_FULL_GROUP_BY

所以这就是为什么你只回来一排,而不是所有的学生。关于如何让所有学生的答案是一个相当简单的答案,只需使用WHERE

SELECT first_name, last_name, username
FROM Students
WHERE Class IN ('JSS1');

如果您希望每个班级使用相同格式的一行,但列出了所有学生,那么您可能需要GROUP_CONCAT

SELECT  class, GROUP_CONCAT(CONCAT(First_name, ' ', last_name)) AS Students
FROM    Students
GROUP BY class;

最后,您应该只有USING具有聚合函数。这方面的一个例子可能是尝试在2个学生中找到课程:

SELECT Class
FROM Students
GROUP BY Class
HAVING COUNT(*) = 2;

答案 1 :(得分:1)

当您想要组合关于聚合函数的一些信息时,已经应用了

GROUP BY子句(作为您想要知道COUNT的最后一个查询)。

因此,如果您有一个聚合函数,并且想要用它来显示标量字段,那么这些字段必须放在GROUP BY子句中。

HAVING子句用于应用聚合值的条件(例如,我想知道COUNT> 1的所有行),我会写:HAVING COUNT() > 1,所以你的所有查询都必须使用一个WHERE条款

您的疑问:

<强> WRONG

SELECT first_name, last_name, username 
FROM students 
GROUP BY class        
HAVING class IN(SS3);

<强> BECOMES

SELECT first_name, last_name, username 
FROM students        
WHERE class IN (SS3);

<强> WRONG

SELECT first_name, last_name, class 
FROM students 
GROUP BY class
HAVING class = 'JSS1';

<强> BECOMES

SELECT first_name, last_name, class 
FROM students 
WHERE class = 'JSS1';

<强> WRONG

SELECT user_id, first_name, last_name, class, COUNT(*) AS total_students
FROM students 
GROUP BY class
HAVING class IN ('JSS1')

<强> BECOMES

SELECT user_id, first_name, last_name, class, COUNT(*) AS total_students
FROM students 
WHERE class IN ('JSS1')
GROUP BY class, user_id, first_name, last_name

答案 2 :(得分:0)

如果你需要给定班级的所有学生,为什么不使用where子句

SELECT first_name, last_name, class 
FROM students 
WHERE class = 'JSS1';

答案 3 :(得分:0)

如果您想列出给定班级的学生,请执行以下操作:

SELECT first_name, last_name, class 
FROM students 
WHERE class = 'JSS1';

查询列出每个班级的学生人数

SELECT class, count(user_id)
FROM students
GROUP BY class;

您会看到这两个查询解决了不同的目的。 group by子句用于将相关数据组合在一起,当然您应该拥有group by中提到的所有列。

您也可以使用分组获取特定班级的学生列表,您的查询将如下所示:

SELECT first_name, last_name, class 
FROM students 
GROUP BY first_name, last_name, class
HAVING class = 'JSS1';

请注意,在上述查询中使用group by是不必要的,您可以使用第一个查询中的where子句轻松地实现结果。