谓词是一种特殊的函数,返回值是真值 。SQL中的真值有3种:True,False,Unknown。
谓词可以按照阶数进行划分:
查询没有参加会议的某人
思路如下:假设所有人每场会议都参加了,将这个集合减去现有的集合就是没有参加会议的集合。
首先生成会议和 出席者的集合
Select DISTINCT(m1.meeting,m2.persion) FROM meeting m1,meeting m2
接着使用EXISTS谓词实现减法
SELECT DISTINCT(m1.meeting,m2.person) FROM meeting m1, meeting m2 WHERE NOT EXISTS( SELECT * FROM meeting m3 WHERE m1.meeting=m3.meeting AND m2.person=m3.person )
请查询所有科目分数都在50分以上的同学
等价于
请查询不存在科目分数小于50分的同学
SELECT DISTINCT student_id FROM testscores t1 WHERE NOT EXISTS( SELECT * FROM testscores t2 WHERE t1.student_id=t2.student_id AND t2.score<50 )
接着我们进阶一下,请求出满足下述条件的学生
SELECT DISTINCT student_id FROM testscores t1 WHERE NOT EXISTS( SELECT * FROM testscores t2 WHERE t1.student_id=t2.student_id AND 1= CASE WHEN t2.subject='语文' AND t2.score<80 THEN 1 CASE WHEN t2.subject='数学' AND t2.score<50 THEN 1 ELSE 0 END )
对于400这个学生,他没有语文成绩,需要排除掉他
SELECT DISTINCT student_id FROM testscores t1 WHERE subject IN ('数学', '语文') AND NOT EXISTS( SELECT * FROM testscores t2 WHERE t1.student_id=t2.student_id AND 1= CASE WHEN t2.subject='语文' AND t2.score<80 THEN 1 CASE WHEN t2.subject='数学' AND t2.score<50 THEN 1 ELSE 0 END ) GROUP BY t1.student_id HAVING COUNT(*)=2 -- 排除400的学生
从上述表中查询出哪些项目已经完成到了工程1
对于某个工程,当工程编号小于等于1时,必须是完成,当工程编号大于1时,必须是等待。等待的个数+完成的个数=总步数。
SELECT project_id FROM projects GROUP BY project_id HAVING COUNT(*)=SUM(CASE WHEN step_nbr <=1 AND status='完成' THEN 1 CASE WHEN tep_nbr >1 AND status='等待' THEN 1 ELSE 0 END)
对于某个工程,当工程编号小于等于1时,必须是完成,当工程编号大于1时,必须是等待。
等价于
对于某个工程,当工程编号小于等于1时,不存在状态是等待,当工程编号大于1时,不存在状态是完成
条件可以写成
CASE WHEN step_nbr <=1 THEN status='完成' ELSE status='等待'END
完整SQL如下
SELECT project_id FROM projects p1 WHERE NOT EXISTS( SELECT * FROM projects p2 WHERE p2.status<>CASE WHEN step_nbr <=1 THEN status='完成' ELSE status='等待' END )
查询全为1的行
SELECT * FROM ArrayTbl WHERE col1 = 1 AND col2 = 1 · · · AND col10 = 1
利用ALL谓词
SELECT * FROM ArrayTbl WHERE 1 = ALL (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10);
至少有一个9
SELECT * FROM ArrayTbl WHERE 9 = ANY (col1, col2, col3, col4, col5, col6, col7, col8, col9, col10);
查询全是NULL的行
SELECT * FROM ArrayTbl WHERE COALESCE(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10) IS NULL;
选出全为1的key
SELECT * FROM ArrayTbl2 a1 WHERE NOT EXISTS( SELECT * FROM ArrayTbl2 a2 WHERE a1.key=a2.key AND a2.val<>1 )
然而这样不只选出了C还出现了A。
原因在于SQL是三值逻辑,而EXISTS是二值逻辑。对于EXISTS而言,没有返回值就是FALSE,返回值就是TRUE。
所以A也会返回。
正确的写法应该排除全为NULL的情况
SELECT * FROM ArrayTbl2 a1 WHERE NOT EXISTS( SELECT * FROM ArrayTbl2 a2 WHERE a1.key=a2.key AND (a2.val<>1 OR a2.val IS NULL) )
或者使用集合的思想
极值函数解决
SELECT key FROM ArrayTbl2 GROUP BY key HAVING MAX(val) = 1 AND MIN(val) = 1;
SELECT key FROM ArrayTbl2 GROUP BY key HAVING COUNT(*)=SUM(CASE WEHN val=1 THEN 1 ELSE 0 END)