在学习《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:
(不定期更新。。。)