一道有意思的面试题 学习公用表达式,outer apply. LATERAL MySQL与SQLServer两种实现方式

原题链接 https://www.modb.pro/issue/8730

出个题,求工作时长
题面
表 A 记录了 A、B、C三人连续工作的开始时间和结束时间,如果结束时间为空,则表示仍然连续工作

name start_date end_date
A 2021-06-30 2021-07-02
A 2021-07-05 2021-07-10
A 2021-07-30 2021-07-31
A 2021-08-02
B 2021-06-30 2021-08-02
B 2021-08-05
C 2021-03-05 2021-03-10
求:
今天是9月1日,该发工资了,求A、B、C三人分别在6月、7月、8月工作的天数,方便结算工资?

name month days
A 6月 1
A 7月 10
A 8月 30
B 6月 1
B 7月 31
B 8月 29
C 6月 0
C 7月 0
C 8月 0


SQL Server解法

with cte1 as
(
  select 'A' as name,'2021-06-30' as start_date,'2021-07-02' as end_date union all
  select 'A' as name,'2021-07-05' as start_date,'2021-07-10' as end_date union all
  select 'A' as name,'2021-07-30' as start_date,'2021-07-31' as end_date union all
  select 'A' as name,'2021-08-02' as start_date,'' as end_date union all
  select 'B' as name,'2021-06-30' as start_date,'2021-08-02' as end_date union all
  select 'B' as name,'2021-08-05' as start_date,'' as end_date union all
  select 'C' as name,'2021-03-05' as start_date,'2021-03-10' as end_date 
),
cte2 as
(
   select DATEADD(DAY,number,'2021-06-01') as datekey from master.dbo.spt_values where type = 'p'
),
cte3 as
(
  select * from  cte2 
  cross join (select distinct [name] from cte1)as t1
  where datekey >'2021-05-31' and datekey<'2021-09-01'
)
,cte4 as
(
select a.name,t.datekey from cte1 a
outer apply (select datekey from cte2 b where b.datekey >= a.start_date and b.datekey <= case when a.end_date = '' then '2021-09-01' else a.end_date end
and datekey<'2021-09-01') as t
group by a.name,t.datekey
)
select convert(varchar(7),a.datekey,120),a.name,count(b.name) as days from  cte3 a
left join cte4 b on a.datekey = b.datekey and a.name = b.name
group by convert(varchar(7),a.datekey,120),a.name
order by a.name,convert(varchar(7),a.datekey,120)

结果
MONTH NAME DAYS
2021-06 A 1
2021-07 A 10
2021-08 A 30
2021-06 B 1
2021-07 B 31
2021-08 B 29
2021-06 C 0
2021-07 C 0
2021-08 C 0


MySQL解法

with cte1 as
(
  select 'A' as name,'2021-06-30' as start_date,'2021-07-02' as end_date union all
  select 'A' as name,'2021-07-05' as start_date,'2021-07-10' as end_date union all
  select 'A' as name,'2021-07-30' as start_date,'2021-07-31' as end_date union all
  select 'A' as name,'2021-08-02' as start_date,'' as end_date union all
  select 'B' as name,'2021-06-30' as start_date,'2021-08-02' as end_date union all
  select 'B' as name,'2021-08-05' as start_date,'' as end_date union all
  select 'C' as name,'2021-03-05' as start_date,'2021-03-10' as end_date 
),  
 cte11 as
 (
select row_number() over(order by table_name,column_name)  as rowno from Information_schema.COLUMNS
) 
,cte2 as
(
   select DATE_ADD('2021-06-01', INTERVAL rowno DAY ) as datekey from cte11
),
cte3 as
(
  select * from  cte2 
  cross join (select name from cte1 group by name)as t1
  where datekey >'2021-05-31' and datekey<'2021-09-01'
)
,cte4 as
(
select a.name,t.datekey from cte1 a
LEFT JOIN LATERAL (select datekey from cte2 b where b.datekey >= a.start_date and b.datekey <= case when a.end_date = '' then '2021-09-01' else a.end_date end
and datekey<'2021-09-01') as t on 1=1
group by a.name,t.datekey
)
select month(a.datekey),a.name,count(b.name) as days from  cte3 a
left join cte4 b on a.datekey = b.datekey and a.name = b.name
group by month(a.datekey),a.name
order by a.name,month(a.datekey)

month name days
6 A 1
7 A 10
8 A 30
6 B 1
7 B 31
8 B 29
6 C 0
7 C 0
8 C 0


mysql 8.0增加了 LATERAL 关键字可以实现 在关联中,左表引表右表,或右表引用左表。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容

  • 前言 最近在群里看到有人发的一道面试题,题目如下: @interface Spark : NSObject @pr...
    luonaerduo阅读 401评论 0 2
  • ------------创建数据库--------------- create database datafrog...
    Thomas_梁阅读 1,101评论 0 0
  • 504b 0304 1400 0008 0800 fa8c 963d 50740baa dffc 0e00 6cd...
    BossOx阅读 3,422评论 0 0
  • 表名和字段 --插入学生表测试数据insert into Student values('01' , '赵雷' ,...
    C1R2阅读 5,322评论 0 1
  • CRON Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义 格式: Se...
    方穹轩阅读 317评论 0 0