按日期时间左连接到第一个出现的行
left join on the first appeared row by datetime
如果class是'Math'或'Biology'有标志为NULL或=0,我们需要与第一个出现的左连接(根据日期)classes'Literature' 或 'English Literature' 来自下面。
如果class是'Math'或'Biology'有标志= 1 那么我们需要左加入最近的(根据日期)classes 'Literature' or 'English Literature'
初始table:
| class | date | flag |
| ------------------ | ----------------------- | ---- |
| Math | 2020-07-07 20:08:00.000 | 0 |
| Biology | 2020-07-07 21:08:00.000 | 1 |
| Math | 2020-07-08 17:08:00.000 | NULL |
| English | 2020-07-10 13:08:00.000 | 0 |
| Literature | 2020-07-15 20:08:00.000 | |
| English Literature | 2020-07-15 21:08:00.000 | |
| Math | 2020-07-15 22:08:00.000 | 1 |
| Literature | 2020-09-09 20:08:00.000 | |
| Math | 2020-09-16 11:08:00.000 | 1 |
| English | 2020-09-17 13:18:00.000 | 0 |
| Biology | 2020-09-19 13:18:00.000 | NULL |
结果table(包含class,不含class = 'Literature','English Literature'):
| class | date | flag | class_2 | date_2 |
| ------- | ----------------------- | ---- | ------------------ | ----------------------- |
| Math | 2020-07-07 20:08:00.000 | 0 | Literature | 2020-07-15 20:08:00.000 |
| Biology | 2020-07-07 21:08:00.000 | 1 | | |
| Math | 2020-07-08 17:08:00.000 | NULL | Literature | 2020-07-15 20:08:00.000 |
| English | 2020-07-10 13:08:00.000 | 0 | | |
| Math | 2020-07-15 22:08:00.000 | 1 | English Literature | 2020-07-15 21:08:00.000 |
| Math | 2020-09-16 11:08:00.000 | 1 | Literature | 2020-09-09 20:08:00.000 |
| English | 2020-09-17 13:18:00.000 | 0 | | |
| Biology | 2020-09-19 13:18:00.000 | NULL | | |
解释:
- Biology 在 2020-09-19 13:18:00.000 没有连接,因为它有 flag NULL和below(晚于'Biology')没有行'Literature'和'English Literature'根据规则。
- 生物学 at 2020-07-07 21:08:00.000 with flag 1 也没有连接,因为在
之前没有“English Literature”或“Literature”
3) Math at 2020-07-07 20:08:00.000 with flag 0 (这是第一行) 。由于flag是0所以我们看第一个出现'Literature'或者'English Literature'这个class之后这个class。第一个出现的是 'Literature' at 2020-07-15 20:08:00.000 所以我们匹配他们
LEFT JOIN 如何根据日期查找最近行或第一行?
没有声称这是最优雅的解决方案;这会起作用:
with Tbl as (
select Class, Date=cast(date as datetime), flag
from (values
('Math',' 2020-07-07 20:08:00.000 ', 0 )
,('Biology',' 2020-07-07 21:08:00.000 ', 1 )
,('Math',' 2020-07-08 17:08:00.000 ', NULL )
,('English',' 2020-07-10 13:08:00.000 ', 0 )
,('Literature',' 2020-07-15 20:08:00.000 ',NULL )
,('English Literature',' 2020-07-15 21:08:00.000 ',NULL )
,('Math',' 2020-07-15 22:08:00.000 ', 1 )
,('Literature',' 2020-09-09 20:08:00.000 ',NULL )
,('Math',' 2020-09-16 11:08:00.000 ', 1 )
,('English',' 2020-09-17 13:18:00.000 ', 0 )
,('Biology',' 2020-09-19 13:18:00.000 ', NULL )
) T(Class, date, flag)
),
T as (
select
Tbl.*
, Case when Class in ('Math','Biology') then 'MB'
when Class in ('Literature','English Literature') then 'LE'
else 'Others'
end as ClassGroup
from Tbl
)
select *
from (select Ta.*
, Tb.Class as B_Class
, Tb.date as B_Date
, Tb.flag as B_Flag
, SeqAsc=row_number() over (partition by ta.ClassGroup, ta.Date order by tb.Date asc)
, SeqDesc=row_number() over (partition by ta.ClassGroup, ta.Date order by tb.Date desc)
from T as Ta
left join
T as Tb
on Ta.ClassGroup='MB'
and Tb.ClassGroup='LE'
and ((coalesce(Ta.flag,0)=0 and Ta.date <= Tb.date)
OR
(coalesce(Ta.flag,0)=1 and Ta.date >= Tb.date)
)
where Ta.ClassGroup in ('MB','Others')
) T
where
(coalesce(T.flag,0)=0 and SeqAsc=1)
or (coalesce(T.flag,0)=1 and SeqDesc=1)
or B_Class is null
order by Date, class
你有一些空白标志值,我假设为 NULL,
您没有说明您使用了哪些数据库产品,我假设是 SqlServer(但它应该适用于大多数产品)。
如果class是'Math'或'Biology'有标志为NULL或=0,我们需要与第一个出现的左连接(根据日期)classes'Literature' 或 'English Literature' 来自下面。
如果class是'Math'或'Biology'有标志= 1 那么我们需要左加入最近的(根据日期)classes 'Literature' or 'English Literature'
初始table:
| class | date | flag |
| ------------------ | ----------------------- | ---- |
| Math | 2020-07-07 20:08:00.000 | 0 |
| Biology | 2020-07-07 21:08:00.000 | 1 |
| Math | 2020-07-08 17:08:00.000 | NULL |
| English | 2020-07-10 13:08:00.000 | 0 |
| Literature | 2020-07-15 20:08:00.000 | |
| English Literature | 2020-07-15 21:08:00.000 | |
| Math | 2020-07-15 22:08:00.000 | 1 |
| Literature | 2020-09-09 20:08:00.000 | |
| Math | 2020-09-16 11:08:00.000 | 1 |
| English | 2020-09-17 13:18:00.000 | 0 |
| Biology | 2020-09-19 13:18:00.000 | NULL |
结果table(包含class,不含class = 'Literature','English Literature'):
| class | date | flag | class_2 | date_2 |
| ------- | ----------------------- | ---- | ------------------ | ----------------------- |
| Math | 2020-07-07 20:08:00.000 | 0 | Literature | 2020-07-15 20:08:00.000 |
| Biology | 2020-07-07 21:08:00.000 | 1 | | |
| Math | 2020-07-08 17:08:00.000 | NULL | Literature | 2020-07-15 20:08:00.000 |
| English | 2020-07-10 13:08:00.000 | 0 | | |
| Math | 2020-07-15 22:08:00.000 | 1 | English Literature | 2020-07-15 21:08:00.000 |
| Math | 2020-09-16 11:08:00.000 | 1 | Literature | 2020-09-09 20:08:00.000 |
| English | 2020-09-17 13:18:00.000 | 0 | | |
| Biology | 2020-09-19 13:18:00.000 | NULL | | |
解释:
- Biology 在 2020-09-19 13:18:00.000 没有连接,因为它有 flag NULL和below(晚于'Biology')没有行'Literature'和'English Literature'根据规则。
- 生物学 at 2020-07-07 21:08:00.000 with flag 1 也没有连接,因为在 之前没有“English Literature”或“Literature”
3) Math at 2020-07-07 20:08:00.000 with flag 0 (这是第一行) 。由于flag是0所以我们看第一个出现'Literature'或者'English Literature'这个class之后这个class。第一个出现的是 'Literature' at 2020-07-15 20:08:00.000 所以我们匹配他们
LEFT JOIN 如何根据日期查找最近行或第一行?
没有声称这是最优雅的解决方案;这会起作用:
with Tbl as (
select Class, Date=cast(date as datetime), flag
from (values
('Math',' 2020-07-07 20:08:00.000 ', 0 )
,('Biology',' 2020-07-07 21:08:00.000 ', 1 )
,('Math',' 2020-07-08 17:08:00.000 ', NULL )
,('English',' 2020-07-10 13:08:00.000 ', 0 )
,('Literature',' 2020-07-15 20:08:00.000 ',NULL )
,('English Literature',' 2020-07-15 21:08:00.000 ',NULL )
,('Math',' 2020-07-15 22:08:00.000 ', 1 )
,('Literature',' 2020-09-09 20:08:00.000 ',NULL )
,('Math',' 2020-09-16 11:08:00.000 ', 1 )
,('English',' 2020-09-17 13:18:00.000 ', 0 )
,('Biology',' 2020-09-19 13:18:00.000 ', NULL )
) T(Class, date, flag)
),
T as (
select
Tbl.*
, Case when Class in ('Math','Biology') then 'MB'
when Class in ('Literature','English Literature') then 'LE'
else 'Others'
end as ClassGroup
from Tbl
)
select *
from (select Ta.*
, Tb.Class as B_Class
, Tb.date as B_Date
, Tb.flag as B_Flag
, SeqAsc=row_number() over (partition by ta.ClassGroup, ta.Date order by tb.Date asc)
, SeqDesc=row_number() over (partition by ta.ClassGroup, ta.Date order by tb.Date desc)
from T as Ta
left join
T as Tb
on Ta.ClassGroup='MB'
and Tb.ClassGroup='LE'
and ((coalesce(Ta.flag,0)=0 and Ta.date <= Tb.date)
OR
(coalesce(Ta.flag,0)=1 and Ta.date >= Tb.date)
)
where Ta.ClassGroup in ('MB','Others')
) T
where
(coalesce(T.flag,0)=0 and SeqAsc=1)
or (coalesce(T.flag,0)=1 and SeqDesc=1)
or B_Class is null
order by Date, class
你有一些空白标志值,我假设为 NULL, 您没有说明您使用了哪些数据库产品,我假设是 SqlServer(但它应该适用于大多数产品)。