1-4 having 子句
寻找缺失的编号
a) 进行升序或降序排序
b) 循环比较每一行和下一行的编号
—查询是否连续
/* 如果有查询结果,说明存在缺失的编号 */
SELECT '存在缺失的编号' AS gap
FROM SeqTbl
HAVING COUNT(*) <> MAX(seq);
—查询缺失编号的最小值
/* 查询缺失编号的最小值 */
SELECT MIN(seq + 1) AS gap
FROM SeqTbl
WHERE (seq+ 1) NOT IN ( SELECT seq FROM SeqTbl);
用having子句进行子查询:求众数
–使用谓词
/* 求众数的SQL语句(1):使用谓词 */
SELECT
income, COUNT(*) AS cnt
FROM
Graduates
GROUP BY income
HAVING COUNT(*) >= ALL (SELECT
COUNT(*)
FROM
Graduates
GROUP BY income)
—使用极值函数
/* 求众数的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);
用having子句进行子查询:求中位数
做法:将集合中元素按大小分为上半部分和下半部分两个子集,同时让这2个子集共同拥有集合正中间的元素,共同部分的元素的平均值即中位数
—使用非等值自连接
/* 求中位数的SQL语句:在HAVING子句中使用非等值自连接 */
SELECT
AVG(DISTINCT income)
FROM
(SELECT
T1.income
FROM
Graduates T1, Graduates T2
GROUP BY T1.income
HAVING SUM(CASE
WHEN T2.income >= T1.income THEN 1
ELSE 0
END) >= COUNT(*) / 2
AND SUM(CASE
WHEN T2.income <= T1.income THEN 1
ELSE 0
END) >= COUNT(*) / 2) TMP;
查询不包含NULL集合
count(*)和count(列名)区别:a.性能 b.count( *)可以用于null,而count(列名)与其他聚合函数一样,先排除null再统计。
/* 查询“提交日期”列内不包含NULL的学院(1):使用COUNT函数 */
SELECT
dpt
FROM
Students
GROUP BY dpt
HAVING COUNT(*) = COUNT(sbmt_date);
—使用case表达式
/* 查询“提交日期”列内不包含NULL的学院(2):使用CASE表达式 */
SELECT
dpt
FROM
Students
GROUP BY dpt
HAVING COUNT(*) = SUM(CASE
WHEN sbmt_date IS NOT NULL THEN 1
ELSE 0
END);
使用case表达式,将“提交日期”不是null的行记为1,否则记为0.这里case表达式相当于判断的函数,用来判断各个元素是否属于满足了某种条件的集合,这样的函数我们称为特征函数(或定义函数)
用关系除法运算进行购物篮分析
应用场景:查询同时服用多种药物的患者;查询UNIX和Oracle两者都精通的程序员等
HAVING子句:针对多行数据(或者说针对集合)设定查询条件
“带余除法”
/* 查询啤酒、纸尿裤和自行车同时在库的店铺 */
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子句的子查询(SELECT COUNT(item) FROM Items) 的返回值是常量3。因此对商品表和店铺的库存管理表进行连接操作后结果是3行的店铺会被选中。
条件改变:"精准关系除法"即选择没有剩余商品的店铺
方法:外连接
/* 精确关系除法运算:使用外连接和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)
AND COUNT(I.item) = (SELECT
COUNT(item)
FROM
Items); /* 条件2 */
条件1 排除count(SI.item)=4的仙台店 ;条件2 排除掉count(I.item)=2的大阪店