书写顺序
依次为: select>from>where>group by>having>order by
,其中select和from是必须的,其他关键词是可选的执行顺序与sql语句的书写顺序并不是一样的
,而是按照下面的顺序来执行:from>where>group by>having>select>order by
当一个查询语句同时出现了where,group by,having,order by的时候,执行顺序和编写顺序是:
- 1.执行where xx对全表数据做筛选,返回第1个结果集。
- 2.针对第1个结果集使用group by分组,返回第2个结果集。
- 3.针对第2个结集执行having xx进行筛选,返回第3个结果集。
- 4.针对第3个结果集中的每1组数据执行select xx,有几组就执行几次,返回第4个结果集。
- 5.针对第4个结果集排序。
数据库SQL语句中 where,group by,having,order by的执行顺序
更加详细的解释: 可以这样去理解group by和聚合函数
在使用group by的时候,select位置处一般会有聚合语句(例如sum),一些没有聚合的字段必须要加到group by 后边
。比如,select a,sum(b) from A group by a //后边必须要有a,否则报错
。
关于sql:必须出现在GROUP BY子句中或在聚合函数中使用
SQL中只要用到聚合函数就一定要用到group by 吗?(不一定)
当只做聚集函数查询时候,就不需要进行分组了
SELECT SUM(TABLE.A ) FROM TABLE
上述SQL不需要使用Group by 进行分组,因为其中没有非聚合字段,所以不用Group by 也可以。
当聚集函数(sum(B))和非聚集字段(A)出一起出现时,需要将非聚集字段(A)进行group by
,分组之后你可以计数(COUNT),求和(SUM),求平均数(AVG)等。
SELECT TABLE.A , MAX(TABLE.B) FROM TABLE GROUP BY TABLE.A
由于B是非聚合字段,则需要使用MAX()或者其他聚合函数进行处理
CREATE TABLE IF NOT EXISTS `test_users` (
`email_id` int(11) unsigned NOT NULL auto_increment,
`email` char(100) NOT NULL,
`passwords` char(64) NOT NULL,
PRIMARY KEY (`email_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
INSERT INTO `test_users` (`email_id`, `email`, `passwords`) VALUES
(1, 'jims@gmail.com', '1e48c4420b7073bc11916c6c1de226bb'),
(2, 'jims@yahoo.com.cn', '5294cef9f1bf1858ce9d7fdb62240546'),
(3, 'default@gmail.com', '5294cef9f1bf1858ce9d7fdb62240546'),
(4, 'jims@gmail.com', null),
(5, 'jims@gmail.com', null),
(6, null, null),
(7, null, null);
distinct 会将选中的所有null
视为一项
格式:
select distince a,b from talbleName
使用:SELECT DISTINCT email,passwords FROM test_users WHERE 1 = 1
,输出:
group by 将选中的所有null
视为一项
格式:
select a, b from tableName groupby a,b
使用:SELECT email, passwords, COUNT(*) FROM test_users WHERE 1 = 1 GROUP BY email,passwords
输出:
count 不会计算null值项,count(null)=0
1.
count(1)与count(*)
得到的结果一致,包含null值。
2.count(字段)
不计算null值
3.count(null)
结果恒为0select count(*) from test_users union all SELECT count(distinct email, passwords) FROM test_users union all select count(*) from ( SELECT email,passwords FROM test_users group by email,passwords ) a;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
我们现在有一张dept_emp表共四个字段,分别是emp_no(员工编号),dept_no(部门编号),from_date(起始时间),to_date(结束时间),记录了员工在某一部门所处时间段,to_date等于9999-01-01的表示目前还在职。
我们现在想知道每个部门有多少名在职员工,步骤如下:
SELECT
dept_no as 部门,
count(emp_no) as 人数
FROM
dept_emp
WHERE
to_date = '9999-01-01'
GROUP BY
dept_no
我们上一步分组之后得到的结果是部门编号,下一步我们可以通过departments去关联出部门名称,语句如下:
SELECT
(SELECT d.dept_name FROM departments d WHERE de.dept_no = d.dept_no) AS 部门,
count(de.emp_no) AS 人数
FROM
dept_emp de
WHERE
de.to_date = '9999-01-01'
GROUP BY
de.dept_no
// ❌❌❌❌错误做法(dept_emp表没有部门名字)❌❌❌❌
SELECT
de.dept_name AS 部门,
count( de.emp_no ) AS 人数
FROM
dept_emp de
WHERE
de.to_date = '9999-01-01'
GROUP BY
de.dept_no
对分组后的结果进行筛选
(即,使用having的前提条件是分组)where后的条件表达式里不允许使用聚合函数
,而having可以我们现在有一张dept_emp表
共四个字段,分别是emp_no(员工编号),dept_no(部门编号),from_date(起始时间),to_date(结束时间),记录了员工在某一部门所处时间段,to_date等于9999-01-01的表示目前还在职。
SELECT
(SELECT d.dept_name FROM departments d WHERE de.dept_no = d.dept_no) AS 部门,
count(de.emp_no ) AS 人数
FROM
dept_emp de
WHERE
de.to_date = '9999-01-01'
GROUP BY
de.dept_no
HAVING // 计算的是分组后,组内的总数
count(de.emp_no ) > 30000
order by 的列必须出现在 distinct 中
出错代码
改正后的代码
讨论:若不使用Distinct关键字,则order by后面的字段不一定要放在seletc中