1. 程式人生 > >SQL中case when子句的使用(連續變數的區間分段統計場景)

SQL中case when子句的使用(連續變數的區間分段統計場景)

某院系2018年計劃舉辦為期一週的學生電競通關能力預測比賽。現已進入決賽,有6位選手入圍。要求根據給定的兩張表如下所示:
UserUser表(
user_id int,—使用者ID
user_name varchar(50),—使用者姓名
user_type int—使用者型別
)
Game_detail表(
day_id date,—玩遊戲的日期
user_id int,—使用者ID
game_id int,—遊戲ID
duration int—玩遊戲的時長(單位:秒)
)
要求:使用一條SQL語句更新該使用者表(UserUser表)的user_type欄位。在遊戲表中(Game_detail表)累計玩過3-6(包含3和6)個不同遊戲的使用者更新為1,玩過6個以上不同遊戲的更新為2,玩過小於3個遊戲或者沒有玩過遊戲的使用者更新為0.

  1. sqlite3實現

1.1.code

import sqlite3 as lite
with lite.connect('E:/C盤jupyter程式碼備份/Kaggle_in/SQLite/rain.forecast.sqlite') as conn:
    curs=conn.cursor()
    #出現database is locked異常,先關閉spyder,重啟Spyder後分次序執行一下三個curs.execute(),每次只能執行一個
    curs.execute("""drop table if exists UserUser;""")
    curs.execute("create table UserUser(user_id int,user_name varchar(25),user_type int)")
    #curs.execute("""drop TABLE Game_detail""")
    curs.execute("""drop table if exists Game_detail;""")
    curs.execute("""CREATE TABLE Game_detail(day_id date,user_id int,game_id int,duration int)""")
    curs.execute("""insert into  UserUser values(100001,'彭彭',0)""")
    curs.execute("""insert into  UserUser values(100002,'玉玉',0)""")
    curs.execute("""insert into  UserUser values(100003,'小青',0)""")
    curs.execute("""insert into  UserUser values(100004,'健健',0)""")
    curs.execute("""insert into  UserUser values(100005,'靜靜',0)""")
    curs.execute("""insert into  UserUser values(100006,'龍龍',0)""")
    #插入遊戲玩耍記錄表
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100001,1012,100)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100002,101,100)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100003,101,90)""")
    curs.execute("""insert into Game_detail values('2018-1-20 9:20:15',100004,1012,60)""")
    curs.execute("""insert into Game_detail values('2018-3-20 9:20:15',100005,1012,170)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100006,101,80)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,1013,150)""")
    curs.execute("""insert into Game_detail values('2018-9-20 9:20:15',100006,1013,100)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100004,1013,100)""")
    curs.execute("""insert into Game_detail values('2018-3-20 9:20:15',100004,1013,100)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100004,1013,40)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100004,1013,50)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100002,1016,60)""")
    curs.execute("""insert into Game_detail values('2018-3-20 9:20:15',100002,1016,90)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100002,1016,100)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100002,1016,180)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100003,1016,130)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100003,1016,200)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100003,1016,30)""")
    curs.execute("""insert into Game_detail values('2018-3-20 9:20:15',100003,1016,110)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100003,108,120)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100003,108,80)""")
    curs.execute("""insert into Game_detail values('2018-2-20 9:20:15',100006,102,90)""")
    curs.execute("""insert into Game_detail values('2018-5-20 9:20:15',100006,102,90)""")
    curs.execute("""insert into Game_detail values('2018-5-20 9:20:15',100006,102,40)""")
    curs.execute("""insert into Game_detail values('2018-5-20 9:20:15',100006,102,50)""")
    curs.execute("""insert into Game_detail values('2018-6-20 9:20:15',100006,102,60)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100005,102,120)""")
    curs.execute("""insert into Game_detail values('2018-8-20 9:20:15',100004,102,150)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100004,102,160)""")
    curs.execute("""insert into Game_detail values('2018-8-20 9:20:15',100004,102,190)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100003,102,180)""")
    curs.execute("""insert into Game_detail values('2018-8-20 9:20:15',100003,102,170)""")
    curs.execute("""insert into Game_detail values('2018-8-20 9:20:15',100003,102,110)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100004,102,120)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100004,102,130)""")
    curs.execute("""insert into Game_detail values('2018-12-20 9:20:15',100005,102,140)""")
    curs.execute("""insert into Game_detail values('2018-12-20 9:20:15',100006,102,170)""")
    curs.execute("""insert into Game_detail values('2018-12-20 9:20:15',100006,102,190)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100006,108,20)""")
    curs.execute("""insert into Game_detail values('2018-11-20 9:20:15',100006,108,130)""")
    curs.execute("""insert into Game_detail values('2018-11-20 9:20:15',100006,101,190)""")
    
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100004,101,120)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100004,100,130)""")
    curs.execute("""insert into Game_detail values('2018-12-20 9:20:15',100005,102,140)""")
    curs.execute("""insert into Game_detail values('2018-12-20 9:20:15',100006,104,170)""")
    curs.execute("""insert into Game_detail values('2018-12-20 9:20:15',100006,101,190)""")
    curs.execute("""insert into Game_detail values('2018-7-20 9:20:15',100006,119,20)""")
    curs.execute("""insert into Game_detail values('2018-11-20 9:20:15',100006,1111,130)""")
    curs.execute("""insert into Game_detail values('2018-11-20 9:20:15',100006,1111,190)""")
   
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,101,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,102,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,103,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,108,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,1016,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,1013,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,1020,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,1012,320)""")
    curs.execute("""insert into Game_detail values('2018-10-20 9:20:15',100006,1018,320)""")
    
    #curs.execute("select * from (SELECT user_id,count(game_id) FROM Game_detail  group by user_id) as A")
    #curs.execute("select * from UserUser as A left join (SELECT user_id,count(game_id) FROM Game_detail  group by user_id) as B on A.user_id=B.user_id")
    #不考慮遊戲編號去重的條件下:
    curs.execute("select A.user_id,user_name,user_type,count from UserUser as A left join (SELECT user_id,count(game_id) as count FROM Game_detail  group by user_id) as B on A.user_id=B.user_id")
    data=curs.fetchall()
    #先查詢所有:
    curs.execute("select * FROM Game_detail")
    data=curs.fetchall()
    #考慮遊戲去重的條件下:
    curs.execute("select user_id, count(distinct game_id) ct \
                     from Game_detail \
                     group by user_id")
    data=curs.fetchall()
    #更新資料:注意sqlite3中update後的UserUser表不能使用連線操作獲得的表物件,無法正常執行通過;mysql卻可以。
    curs.execute("update UserUser set user_type =(\
            select case when ct > 6 then 2\
                 when ct < 3 then 0\
                 else 1 end \
            from (select user_id, count(distinct game_id) ct from Game_detail group by user_id ) as g \
            where  UserUser.user_id=g.user_id)")      
    curs.execute("select * from UserUser") 
    data=curs.fetchall()

1.2.效果
1.2.1.UserUser:
1 (100001, ‘彭彭’, 0)
2 (100002, ‘玉玉’, 0)
3 (100003, ‘小青’, 0)
4 (100004, ‘健健’, 0)
5 (100005, ‘靜靜’, 0)
6 (100006, ‘龍龍’, 0)
1.2.2.Game_detail:
0 (‘2018-10-20 9:20:15’, 100001, 1012, 100)
1 (‘2018-10-20 9:20:15’, 100002, 101, 100)
……
56 (‘2018-10-20 9:20:15’, 100006, 1020, 320)
57 (‘2018-10-20 9:20:15’, 100006, 1012, 320)
58 (‘2018-10-20 9:20:15’, 100006, 1018, 320)
1.2.3.使用左連線的實現效果
0 (100001, ‘彭彭’, 0, 1)
1 (100002, ‘玉玉’, 0, 2)
2 (100003, ‘小青’, 1, 4)
3 (100004, ‘健健’, 1, 5)
4 (100005, ‘靜靜’, 0, 2)
5 (100006, ‘龍龍’, 2, 12)
1.2.4.不使用連線的快速寫法(case when 子句實現

)
0 (100001, ‘彭彭’, 0)
1 (100002, ‘玉玉’, 0)
2 (100003, ‘小青’, 1)
3 (100004, ‘健健’, 1)
4 (100005, ‘靜靜’, 0)
5 (100006, ‘龍龍’, 2)
2. MySQL實現

drop table if exists UserUser;

create table UserUser(
    user_id int primary key,
    user_name varchar(25),
    user_type int
    );
insert into  UserUser values(100001,'彭彭',0);
insert into  UserUser values(100002,'玉玉',0);
insert into  UserUser values(100003,'小青',0);
insert into  UserUser values(100004,'健健',0);
insert into  UserUser values(100005,'靜靜',0);
insert into  UserUser values(100006,'龍龍',0);

select * from UserUser;

drop table if exists Game_detail;
create table Game_detail(
    day_id date,
    user_id int,
    game_id int,
    duration int,
    primary key(day_id,user_id,game_id),
    foreign key(user_id) references UserUser(user_id)
    );
    
insert into Game_detail values('2018-10-20',100001,1011,100);
insert into Game_detail values('2018-10-21',100002,1011,100);
insert into Game_detail values('2018-10-22',100003,1012,90);
insert into Game_detail values('2018-1-20',100004,1013,60);
insert into Game_detail values('2018-3-20',100005,1014,170);
insert into Game_detail values('2018-10-21',100006,1011,100);
insert into Game_detail values('2018-12-2',100001,1011,100);
insert into Game_detail values('2018-10-21',100002,1014,100);
insert into Game_detail values('2018-10-20',100003,1015,90);

insert into Game_detail values('2018-3-14',100005,1012,170);
insert into Game_detail values('2018-10-25',100006,1012,100);
insert into Game_detail values('2018-11-20',100001,1017,100);
insert into Game_detail values('2018-10-27',100002,1015,100);
insert into Game_detail values('2018-10-24',100003,1014,90);

insert into Game_detail values('2018-3-10',100005,1013,170);
insert into Game_detail values('2018-10-23',100006,1013,100);
insert into Game_detail values('2018-11-20',100001,1011,100);
insert into Game_detail values('2018-10-29',100002,1014,100);
insert into Game_detail values('2018-10-14',100003,1015,90);

insert into Game_detail values('2018-3-20',100005,1012,170);
insert into Game_detail values('2018-10-20',100006,1017,100);
insert into Game_detail values('2018-8-20',100001,1018,100);
insert into Game_detail values('2018-9-20',100002,1019,100);
insert into Game_detail values('2018-10-20',100003,1014,90);
insert into Game_detail values('2018-3-20',100005,1013,170);
insert into Game_detail values('2018-10-24',100006,1014,100);
insert into Game_detail values('2018-1-20',100003,1013,90);

insert into Game_detail values('2018-3-20',100005,1011,170);
insert into Game_detail values('2018-10-23',100006,1012,100);
insert into Game_detail values('2018-10-24',100006,1013,100);
insert into Game_detail values('2018-10-28',100006,1015,100);
insert into Game_detail values('2018-10-29',100006,1019,100);
insert into Game_detail values('2018-11-22',100006,1017,100);

select * from Game_detail;

-- 篩選統計每個人玩的遊戲數量
select UserUser.user_id as uid,count(distinct game_id)  as  cnt from UserUser
join Game_detail on UserUser.user_id=Game_detail.user_id
group by UserUser.user_id;

-- update User表中的user_type欄位
update UserUser join 
(select UserUser.user_id as uid,count(distinct game_id) as cnt from UserUser
join Game_detail on UserUser.user_id=Game_detail.user_id
group by UserUser.user_id) as tmp
on UserUser.user_id=tmp.uid
set user_type=(
	case 
	when tmp.cnt<3 then 0 
        when tmp.cnt between 3 and 6 then 1 
        when tmp.cnt>6 then 2
        end);
        
select * from UserUser;

或者:
update UserUser as u
   set u.user_type =
       (select 
        case when ct > 6 then 2
             when ct < 3 then 0
             else 1 end
        from (select user_id, count(distinct game_id) ct
                 from Game_detail
                 group by user_id) as g  #派生表都要給它起個名字
         where  u.user_id=g.user_id);

  1. Oracle實現
merge into UserUser u
using (select user_id, count(distinct game_id) ct
from game_details
group by user_id) g
on (u.user_id=g.user_id) 
when matched then   
update      
set u.user_type=(
case
     when ct > 6 then  2
     when ct < 3 then   0
     else  1  end
)
  1. SQLserver版本
    //user是SQLserver的保留變數 不能做表名.update語句不支援別名
update Users
set user_type =
(select case
        when ct > 6 then 2
        when ct < 3 then 0
        else 1 end
	from  (select user_id, count(distinct game_id) ct
		    from Game_detail
		    group by user_id) g
        where  Users.user_id = g.user_id);