运行环境 win10 / oracle(DB11g)
思路:
一个集合中,如果元素最大值和最小值相等,那么这个集合中肯定只用一种值
-- 创表
create table teams_10
(
member varchar(10),
team_id integer,
status1 varchar(10)
);
insert into teams_10 values('乔', 1, '待命');
insert into teams_10 values('肯', 1, '出勤中');
insert into teams_10 values('米克', 1, '待命');
insert into teams_10 values('卡伦', 2, '出勤中');
insert into teams_10 values('凯斯', 2, '休息');
insert into teams_10 values('简', 3, '待命');
insert into teams_10 values('哈特', 3, '待命');
insert into teams_10 values('迪克', 3, '待命');
insert into teams_10 values('贝斯', 4, '待命');
insert into teams_10 values('阿伦', 5, '出勤中');
insert into teams_10 values('罗伯特', 5, '休息');
insert into teams_10 values('卡跟', 5, '待命');
SQL解决:
-- 1-直接找出可出勤的队
select team_id
from teams_10
group by team_id
having max(status1) = '待命'
and min(status1) = '待命'
;
-- 2-对出勤的队打标签
select team_id
,case when max(status1) = '待命' and min(status1) = '待命'
then '全部在待命'
else '队长人手不够' end as status1
from teams_10
group by team_id
;
结果:
-- 1
TEAM_ID
----------
4
3
-- 2
TEAM_ID STATUS1
---------- ------------
1 队长人手不够
2 队长人手不够
4 全部在待命
5 队长人手不够
3 全部在待命
-- 创表
create table materials_10
(
center varchar(10),
recieve_date date,
material varchar(6)
)
;
insert into materials_10 values ('东京',to_date('2007-04-01','yyyy-mm-dd'),'锡');
insert into materials_10 values ('东京',to_date('2007-04-12','yyyy-mm-dd'),'锌');
insert into materials_10 values ('东京',to_date('2007-05-17','yyyy-mm-dd'),'铝');
insert into materials_10 values ('东京',to_date('2007-05-20','yyyy-mm-dd'),'锌');
insert into materials_10 values ('大阪',to_date('2007-04-20','yyyy-mm-dd'),'铜');
insert into materials_10 values ('大阪',to_date('2007-04-22','yyyy-mm-dd'),'镍');
insert into materials_10 values ('大阪',to_date('2007-04-29','yyyy-mm-dd'),'铅');
insert into materials_10 values ('名古屋',to_date('2007-03-15','yyyy-mm-dd'),'钛');
insert into materials_10 values ('名古屋',to_date('2007-04-01','yyyy-mm-dd'),'钢');
insert into materials_10 values ('名古屋',to_date('2007-04-24','yyyy-mm-dd'),'钢');
insert into materials_10 values ('名古屋',to_date('2007-05-02','yyyy-mm-dd'),'镁');
insert into materials_10 values ('名古屋',to_date('2007-05-10','yyyy-mm-dd'),'钛');
insert into materials_10 values ('福冈',to_date('2007-05-10','yyyy-mm-dd'),'锌');
insert into materials_10 values ('福冈',to_date('2007-05-28','yyyy-mm-dd'),'锡');
SQL解决:
select center
from materials_10
group by center
having count(material) <> count(distinct material)
;
结果:
CENTER
----------
名古屋
东京
用Having可以找出那个生产中心有存在重复材料生产,但是不能解决是哪一种材料重复了,为实现该目的,可以用exists ,他可以呈现更多的结果
select center, material
from materials_10 m1
where exists
(select *
from materials_10 m2
where m1.center = m2.center
and m1.recieve_date <> m2.recieve_date
and m1.material = m2.material
)
;
-- 结果
CENTER MATERI
---------- ------
东京 锌
东京 锌
名古屋 钛
名古屋 钢
名古屋 钢
名古屋 钛
思路:
通过case表达式生成特征函数,以满足各种条件
-- 创表
create table testresults_10
(
student_id varchar(4),
classs varchar(2),
sex varchar(4),
score integer
)
;
insert into testresults_10 values('001','A','男',100);
insert into testresults_10 values('002','A','女',100);
insert into testresults_10 values('003','A','女',49);
insert into testresults_10 values('004','A','男',30);
insert into testresults_10 values('005','B','女',100);
insert into testresults_10 values('006','B','男',92);
insert into testresults_10 values('007','B','男',80);
insert into testresults_10 values('008','B','男',80);
insert into testresults_10 values('009','B','女',10);
insert into testresults_10 values('010','C','男',92);
insert into testresults_10 values('011','C','男',80);
insert into testresults_10 values('012','C','女',21);
insert into testresults_10 values('013','D','女',100);
insert into testresults_10 values('014','D','女',0);
insert into testresults_10 values('015','D','女',0);
SQL解决:
-- 查询75%以上的学生分数都在80分以上的班级
select classs
from testresults_10
group by classs
having count(*)*0.75
<= sum(case when score >=80 then 1 else 0 end)
;
-- 结果
CL
--
B
-- 查询出分数在50分以上的男生的人数比分数在50分以上的女生多的班级
select classs
from testresults_10
group by classs
having sum(case when score >= 50 and sex = '男' then 1 else 0 end)
> sum(case when score >= 50 and sex = '女' then 1 else 0 end)
;
-- 结果
CL
--
B
C
-- 查询出女生平均分比男生平均分高的班级(对空集求平均为NULL)
select classs
from testresults_10
group by classs
having avg(case when sex = '男' then score end )
< avg(case when sex = '女' then score end )
;
-- 结果
CL
--
A
-- 创表
create table materials_10_t
(
center varchar(10),
recieve_date date,
material varchar(6),
orgland varchar(6)
)
;
insert into materials_10_t values ('东京',to_date('2007-04-01','yyyy-mm-dd'),'锡','智利');
insert into materials_10_t values ('东京',to_date('2007-04-12','yyyy-mm-dd'),'锌','泰国');
insert into materials_10_t values ('东京',to_date('2007-05-17','yyyy-mm-dd'),'铝','巴西');
insert into materials_10_t values ('东京',to_date('2007-05-20','yyyy-mm-dd'),'锌','泰国');
insert into materials_10_t values ('大阪',to_date('2007-04-20','yyyy-mm-dd'),'铜','澳大利亚');
insert into materials_10_t values ('大阪',to_date('2007-04-22','yyyy-mm-dd'),'镍','南非');
insert into materials_10_t values ('大阪',to_date('2007-04-29','yyyy-mm-dd'),'铅','印度');
insert into materials_10_t values ('名古屋',to_date('2007-03-15','yyyy-mm-dd'),'钛','玻利维亚');
insert into materials_10_t values ('名古屋',to_date('2007-04-01','yyyy-mm-dd'),'钢','智利');
insert into materials_10_t values ('名古屋',to_date('2007-04-24','yyyy-mm-dd'),'钢','阿根廷');
insert into materials_10_t values ('名古屋',to_date('2007-05-02','yyyy-mm-dd'),'镁','智利');
insert into materials_10_t values ('名古屋',to_date('2007-05-10','yyyy-mm-dd'),'钛','泰国');
insert into materials_10_t values ('福冈',to_date('2007-05-10','yyyy-mm-dd'),'锌','美国');
insert into materials_10_t values ('福冈',to_date('2007-05-28','yyyy-mm-dd'),'锡','俄罗斯');
SQL解决:
-- 1、exists
select center, material, orgland
from materials_10_t m1
where exists
(select *
from materials_10_t m2
where m1.center = m2.center
and m1.recieve_date <> m2.recieve_date
and m1.material = m2.material
and m1.orgland = m2.orgland
)
;
-- 2、having
select center, orgland
from materials_10_t
group by center, orgland
having count(material) <> count(distinct material)
and count(orgland) <> count(distinct orgland)
;
结果:
-- 1
CENTER MATERI ORGLAN
---------- ------ ------
东京 锌 泰国
东京 锌 泰国
-- 2
CENTER ORGLAN
---------- ------
东京 泰国
(数学的分数在80分以上/语文的分数在50分以上)
-- 创表
create table testscores(
student_id INTEGER,
subject1 varchar(10),
score INTEGER
);
insert into testscores values(100, '数学', 100);
insert into testscores values(100, '语文', 80);
insert into testscores values(100, '理化', 80);
insert into testscores values(200, '数学', 80);
insert into testscores values(200, '语文', 95);
insert into testscores values(300, '数学', 40);
insert into testscores values(300, '语文', 90);
insert into testscores values(300, '社会', 55);
insert into testscores values(400, '数学', 80);
SQL解决:
-- 数学的分数在80分以上/语文的分数在50分以上
-- 回忆exists
select *
from testscores t1
where not EXISTS
( select *
from testscores t2
where t1.student_id = t2.student_id
and ( (subject1 = '数学' and score <= 80)
or (subject1 = '语文' and score <= 50) )
)
;
-- 用having 空集为NULL
select student_id
from testscores
group by student_id
having 2 = sum(case when subject1 = '数学' and score > 80 then 1
when subject1 = '语文' and score > 50 then 1
end)
;
结果:
-- 1
STUDENT_ID SUBJECT1 SCORE
---------- ---------- ----------
100 理化 80
100 语文 80
100 数学 100
-- 2
STUDENT_ID
----------
100
内容多来自 《SQL进阶教材》,仅做笔记。练习代码均为原创。