SQL进阶之HAVING练习
2020-07-13 05:58
330 查看
SQL进阶之HAVING用法
一、HAVING子句简介
HAVING是在sql的运行完后做的一个判断常跟聚合写法后面
二、HAVING实操
注:版本使用:mysql5.1.73
以下代码均可直接cv在mysql练习
1.CreateTable
/* 寻找缺失的编号 */ CREATE TABLE SeqTbl (seq INTEGER PRIMARY KEY, name VARCHAR(16) NOT NULL); INSERT INTO SeqTbl VALUES(1, '迪克'); INSERT INTO SeqTbl VALUES(2, '安'); INSERT INTO SeqTbl VALUES(3, '莱露'); INSERT INTO SeqTbl VALUES(5, '卡'); INSERT INTO SeqTbl VALUES(6, '玛丽'); INSERT INTO SeqTbl VALUES(8, '本'); /* 用HAVING子句进行子查询:求众数(求中位数时也用本代码) */ CREATE TABLE Graduates (name VARCHAR(16) PRIMARY KEY, income INTEGER NOT NULL); INSERT INTO Graduates VALUES('桑普森', 400000); INSERT INTO Graduates VALUES('迈克', 30000); INSERT INTO Graduates VALUES('怀特', 20000); INSERT INTO Graduates VALUES('阿诺德', 20000); INSERT INTO Graduates VALUES('史密斯', 20000); INSERT INTO Graduates VALUES('劳伦斯', 15000); INSERT INTO Graduates VALUES('哈德逊', 15000); INSERT INTO Graduates VALUES('肯特', 10000); INSERT INTO Graduates VALUES('贝克', 10000); INSERT INTO Graduates VALUES('斯科特', 10000); /* 用关系除法运算进行购物篮分析 */ CREATE TABLE Items (item VARCHAR(16) PRIMARY KEY); CREATE TABLE ShopItems (shop VARCHAR(16), item VARCHAR(16), PRIMARY KEY(shop, item)); INSERT INTO Items VALUES('啤酒'); INSERT INTO Items VALUES('纸尿裤'); INSERT INTO Items VALUES('自行车'); INSERT INTO ShopItems VALUES('仙台', '啤酒'); INSERT INTO ShopItems VALUES('仙台', '纸尿裤'); INSERT INTO ShopItems VALUES('仙台', '自行车'); INSERT INTO ShopItems VALUES('仙台', '窗帘'); INSERT INTO ShopItems VALUES('东京', '啤酒'); INSERT INTO ShopItems VALUES('东京', '纸尿裤'); INSERT INTO ShopItems VALUES('东京', '自行车'); INSERT INTO ShopItems VALUES('大阪', '电视'); INSERT INTO ShopItems VALUES('大阪', '纸尿裤'); INSERT INTO ShopItems VALUES('大阪', '自行车'); /* 查询不包含NULL的集合 */ CREATE TABLE Students (student_id INTEGER PRIMARY KEY, dpt VARCHAR(16) NOT NULL, sbmt_date DATE); INSERT INTO Students VALUES(100, '理学院', '2005-10-10'); INSERT INTO Students VALUES(101, '理学院', '2005-09-22'); INSERT INTO Students VALUES(102, '文学院', NULL); INSERT INTO Students VALUES(103, '文学院', '2005-09-10'); INSERT INTO Students VALUES(200, '文学院', '2005-09-22'); INSERT INTO Students VALUES(201, '工学院', NULL); INSERT INTO Students VALUES(202, '经济学院', '2005-09-25');
2.Sample
/* 需求:修改编号缺失的检查逻辑,使结果总是返回一行数据 */ /* 写法一:union+having*/ SELECT ' 存在缺失的编号' AS gap FROM SeqTbl HAVING COUNT(*) <> MAX(seq) UNION ALL SELECT ' 不存在缺少的编号' AS gap FROM SeqTbl HAVING COUNT(*) = MAX(seq); /* 写法二:case when*/ SELECT CASE WHEN COUNT(*) <> MAX(seq) THEN '存在缺失的编号' ELSE '不存在缺失的编号' END AS gap FROM SeqTbl; /*查询缺失编号的最小值*/ SELECT MIN(seq+1) AS gap FROM SeqTbl WHERE seq is not null and (seq+1) NOT IN (SELECT seq FROM SeqTbl) 注:若是seq存在空值就会出现没有结果的情况,使用 not in 一定要注意null /* 练习“特征函数” 查找所有学生都在9月份提交完成的学院(1):使用BETWEEN谓词 */ SELECT dpt FROM Students GROUP BY dpt HAVING COUNT(*) = SUM(CASE WHEN sbmt_date BETWEEN '2005-09-01' AND '2005-09-30' THEN 1 ELSE 0 END); /* 求众数的SQL语句(1):使用谓词all */ SELECT income, COUNT(*) AS cnt FROM Graduates GROUP BY income HAVING COUNT(*) >= ALL ( SELECT COUNT(*) FROM Graduates GROUP BY income); 注:使用谓词ALL,在值为null或空集时也会出现问题可以使用极值代替 /* 求众数的SQL语句(2):使用极值函数 */ SELECT income, COUNT(*) AS cnt FROM Graduates GROUP BY income HAVING COUNT(*) >= ( SELECT MAX(cnt) FROM ( SELECT COUNT(*) AS cnt FROM Graduates GROUP BY income) TMP) ; /* 求中位数的SQL语句:在HAVING子句中使用非等值自连接 */ SELECT AVG(DISTINCT income) FROM (SELECT T1.income FROM Graduates T1, Graduates T2 GROUP BY T1.income /* S1的条件 */ HAVING SUM(CASE WHEN T2.income >= T1.income THEN 1 ELSE 0 END) >= COUNT(*) / 2 /* S2的条件 */ AND SUM(CASE WHEN T2.income <= T1.income THEN 1 ELSE 0 END) >= COUNT(*) / 2 ) TMP; /*需求:查询“提交日期”列内不包含NULL的学院*/ /* (1):使用COUNT函数 */ SELECT dpt FROM Students GROUP BY dpt HAVING COUNT(*) = COUNT(sbmt_date); /* (2):使用CASE表达式 */ SELECT dpt FROM Students GROUP BY dpt HAVING COUNT(*) = SUM(CASE WHEN sbmt_date IS NOT NULL THEN 1 ELSE 0 END); /*需求: 查询啤酒、纸尿裤和自行车同时在库的店铺 */ /* 错误的SQL语句 */ SELECT DISTINCT shop FROM ShopItems WHERE item IN (SELECT item FROM Items); 注:错误原因in的话只要满足其一都包含,这时候可以用HAVING来来解决问题 /* 正确的SQL语句 */ SELECT SI.shop FROM ShopItems SI, Items I WHERE SI.item = I.item GROUP BY SI.shop HAVING COUNT(SI.item) = (SELECT COUNT(item) FROM Items); 注:如果把HAVING COUNT(SI.item) = (SELECT COUNT(item) FROM Items)改成HAVING COUNT(SI.item)=COUNT(I.item),结果就会有问题,原因是受了连接操作的影响 例:/* COUNT(I.item)的值已经不一定是3了 */ SELECT SI.shop, COUNT(SI.item), COUNT(I.item) FROM ShopItems SI, Items I WHERE SI.item = I.item GROUP BY SI.shop; /* 精确关系除法运算:使用外连接和COUNT函数 */ SELECT SI.shop FROM ShopItems AS SI LEFT OUTER JOIN Items AS I ON SI.item=I.item GROUP BY SI.shop HAVING COUNT(SI.item) = (SELECT COUNT(item) FROM Items) /* 条件1 */ AND COUNT(I.item) = (SELECT COUNT(item) FROM Items); /* 条件2 */ /* 购物篮分析问题的一般变化 select 嵌套+子查询*/ SELECT SI.shop, COUNT(SI.item) AS my_item_cnt, (SELECT COUNT(item) FROM Items) - COUNT(SI.item) AS diff_cnt FROM ShopItems SI, Items I WHERE SI.item = I.item GROUP BY SI.shop;
参考资料:《SQL进阶教程》| MICK
相关文章推荐
- 基本SQL语句练习(order by,group by,having)
- SQL练习进阶--SQL实例讲解
- SQL进阶之关联子查询练习
- SQL 练习编写能力(1) (GROUP BY HAVING)
- XCTF攻防世界web进阶练习_ 5_mfw
- T-SQL查询进阶--基于列的逻辑表达式
- ORACLE PL/SQL练习(二)
- 1月31 SQL巩固练习(45道题)
- #写作业# PTA 中M2018秋C入门和进阶练习
- sql查询-sql练习
- 2014-01-04 SQL练习
- sql中的group by 和 having 用法解析
- SQL基础_第六章 SELECT进阶
- LINQ体验(7)——LINQ to SQL语句之Group By/Having和Exists/In/Any/All/Contains
- SQL进阶(七) SELECT INTO和INSERT INTO SELECT
- 浅谈sql语句中GROUP BY 和 HAVING的使用方法
- LINQ体验(7)——LINQ to SQL语句之Group By/Having和Exists/In/Any/All/Contains
- 菜鸟到高手:SQL开发进阶常用精妙语句
- T-SQL查询进阶—理解SQL Server中的锁
- sql语句练习50题