按日期时间左连接到第一个出现的行

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 |                    |                         |

解释:

  1. Biology2020-09-19 13:18:00.000 没有连接,因为它有 flag NULLbelow(晚于'Biology')没有行'Literature''English Literature'根据规则。
  2. 生物学 at 2020-07-07 21:08:00.000 with flag 1 也没有连接,因为在
  3. 之前没有“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(但它应该适用于大多数产品)。