在学习《SQL进阶教程学习》的记录笔记,现学现用效率真的很高,带着问题学习,记忆会深很多很多。
CASE表达式有简单CASE表达式(simple caseexpression)和搜索CASE表达式(searched case expression)两种写法。
--简单CASE表达式
CASE sex
WHEN '1' THEN ’男’
WHEN '2' THEN ’女’
ELSE ’其他’ END
--搜索CASE表达式
CASE WHEN sex ='1'THEN’男’
WHEN sex ='2'THEN’女’
ELSE ’其他’ END
tips:
进行不同条件的统计是CASE表达式的著名用法之一。
-- 男性人口
SELECT pref_name,
SUM(population)
FROM PopTbl2
WHERE sex ='1'
GROUP BY pref_name;
-- 女性人口
SELECT pref_name,
SUM(population)
FROM PopTbl2
WHERE sex ='2'
GROUP BY pref_name;
SELECT pref_name,
--男性人口
SUM( CASE WHEN sex ='1'THEN population ELSE 0 END) AS cnt_m,
--女性人口
SUM( CASE WHEN sex ='2'THEN population ELSE 0 END) AS cnt_f
FROM PopTbl2
GROUP BY pref_name;
--条件1
UPDATE Salaries
SET salary = salary * 0.9
WHERE salary >= 300000;
--条件2
UPDATE Salaries
SET salary = salary * 1.2
WHERE salary >= 250000 AND salary < 280000;
两个UPDATE函数依次执行的话,可能会反复操作同一个数据,因此会造成错误。因此使用UPDATE与CASE函数结合,而且因为只需执行一次,所以速度也更快:
--用CASE表达式写正确的更新操作
UPDATE Salaries
SET salary = CASE WHEN salary >= 300000
THEN salary * 0.9
WHEN salary >= 250000 AND salary < 280000
THEN salary * 1.2
ELSE salary END;
--1.将a转换为中间值d
UPDATE SomeTable
SET p_key ='d'
WHERE p_key ='a';
--2.将b调换为a
UPDATE SomeTable
SET p_key ='a'
WHERE p_key ='b';
--3.将d调换为b
UPDATE SomeTable
SET p_key ='b'
WHERE p_key ='d';
没有必要执行3次UPDATE操作,因此可以用UPDATE结合CASE:
--用CASE表达式调换主键值
UPDATE SomeTable
SET p_key = CASE WHEN p_key ='a'
THEN 'b'
WHEN p_key ='b'
THEN 'a'
ELSE p_key END
WHERE p_key IN ('a', 'b');
--表的匹配:使用IN谓词
SELECT course_name,
CASE WHEN course_id IN
(SELECT course_id FROM OpenCourses
WHERE month = 200706) THEN'○'
ELSE'×'END AS "6月",
CASE WHEN course_id IN
(SELECT course_id FROM OpenCourses
WHERE month = 200707) THEN'○'
ELSE'×'END AS "7月",
CASE WHEN course_id IN
(SELECT course_id FROM OpenCourses
WHERE month = 200708) THEN'○'
ELSE'×'END AS "8月"
FROM CourseMaster;
--表的匹配:使用EXISTS谓词
SELECT CM.course_name,
CASE WHEN EXISTS
(SELECT course_id FROM OpenCourses OC
WHERE month = 200706
AND OC.course_id = CM.course_id) THEN'○'
ELSE'×'END AS "6月",
CASE WHEN EXISTS
(SELECT course_id FROM OpenCourses OC
WHERE month = 200707
AND OC.course_id = CM.course_id) THEN'○'
ELSE'×'END AS "7月",
CASE WHEN EXISTS
(SELECT course_id FROM OpenCourses OC
WHERE month = 200708
AND OC.course_id = CM.course_id) THEN'○'
ELSE'×'END AS "8月"
FROM CourseMaster CM;
tips:
使用EXISTS时还要把两个表格的相同列表示出来。
方法一、使用窗口函数:
--排序:使用窗口函数
SELECT name, price,
RANK() OVER (ORDER BY price DESC) AS rank_1,
DENSE_RANK() OVER (ORDER BY price DESC) AS rank_2
FROM Products;
tips:
方法二、使用自连接:
--排序从1开始。如果已出现相同位次,则跳过之后的位次
SELECT P1.name,
P1.price,
(SELECT COUNT(P2.price)
FROM Products P2
WHERE P2.price > P1.price) + 1 AS rank_1
FROM Products P1
ORDER BY rank_1;
二值逻辑:true、false
三值逻辑(three-valued logic):true、false、unknown
两种NULL分别指的是“未知”(unknown)和“不适用”(not applicable,inapplicable)。“未知”指的是“虽然现在不知道,但加上某些条件后就可以知道”;而“不适用”指的是“无论怎么努力都无法知道”。
三个真值之间的优先级顺序:
SQL是一种基于“面向集合”思想设计的语言,同样具备这种设计思想的语言很少;最开始学习过了某种理念的语言后,心理上会形成思维定式,从而妨碍我们理解另一种理念的语言。
-- 如果有查询结果,说明存在缺失的编号
SELECT’存在缺失的编号’AS gap
FROM SeqTbl
HAVING COUNT(*) <> MAX(seq);
如果这个查询结果有1行,说明存在缺失的编号;如果1行都没有,说明不存在缺失的编号。
-- 查询缺失编号的最小值
SELECT MIN(seq + 1) AS gap
FROM SeqTbl
WHERE (seq+ 1) NOT IN ( SELECT seq FROM SeqTbl);
tips:
众数(mode):指的是在群体中出现次数最多的值.
--求众数的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 ) ;
中位数(median):指的是将集合中的元素按升序排列后恰好位于正中间的元素。
--求中位数的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;
COUNT函数的使用方法有COUNT(*)和COUNT(列名)两种,它们的区别有两个:
--查询“提交日期”列内不包含NULL的学院(1):使用COUNT函数
SELECT dpt
FROM Students
GROUP BY dpt
HAVING COUNT(*) = COUNT(sbmt_date);
--查询“提交日期”列内不包含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);
tips:
参数是子查询时,使用EXISTS代替IN
tips:
使用EXISTS时更快的原因有以下两个:
tips:
(不定期更新。。。)