获取和筛选日期 SQL

Get and filter dates SQL

我有这个table没有pk

| Peo  | Pos | DATE_BEGIN | DATE_END   | XXXX |
+------+-----+------------+------------+------+
| 9302 | 8   | 2017-10-02 | 2017-12-31 | NULL |
| 9302 | 8   | 2018-01-01 | 2018-01-01 | NULL |
| 9302 | 8   | 2018-01-02 | 2018-05-31 | NULL |
| 9302 | 8   | 2018-06-01 | 9999-12-31 | NULL |

我想获得 Pos 8 中从旧的 DATE_BEGIN 到较新的 Date_END 的时间传递,当未定义时可能是 9999-12-31,在这种情况下将是实际日期.为此 table 将是 2017-10-02 到 9999-12-31(2020/06/23,实际日期)。

一个问题是,对于下面的 table,它应该只得到最后一行,因为这个人在 Pos 中的总时间已经改变了。所以将是 (2018-06-01) - (9999-12-31 - 实际日期)

| Peo  | Pos | DATE_BEGIN | DATE_END   | XXXX |
+------+-----+------------+------------+------+
| 9302 | 8   | 2017-10-02 | 2017-12-31 | NULL |
| 9302 | 8   | 2018-01-01 | 2018-01-01 | NULL |
| 9302 | 7   | 2018-01-02 | 2018-05-31 | NULL |
| 9302 | 8   | 2018-06-01 | 9999-12-31 | NULL |

我想你想要:

select
    peo,
    datediff(
        day, 
        min(date_begin), 
        case when max(date_end) = '9999-12-31' then cast(getdate() as date) else max(date_end) end
    ) days
from mytable t
where not exists (
    select 1 
    from mytable t1 
    where 
        t1.peo = t.peo 
        and t1.date_begin > t.date_end 
        and t1.pos <> 8
)
group by peo

对于每个 peowhere 子句过滤最后一系列 pos8 的记录的 table。然后查询按 peo 聚合,计算最小值 date_begin 和最大值 date_end 之间的差值(如果 date_end'9999-12-31',我们使用当前改为日期)。

这是一个典型的间隙和孤岛问题。您正在寻找具有 pos = 8.

的最终行序列(每个 peo

因此,对于每个 peo,您都需要按日期倒数,寻找序列中的中断点。以这种方式分组后,您将只保留第一个这样的分组,然后聚合:

with data as (
    select *,
        sum(case when pos = 8 then 0 else 1 end)
            over (partition by peo order by date_begin desc) as brk
    from TblX t
    -- this is unnecessary if the latest row is always pos = 8
    where date_begin <= (
        select max(t2.date_begin) from TblX t2
        where t2.peo = t.peo and t2.pos = 8
    )
)
select
    peo,
    min(date_begin) as date_begin,
    case max(date_end)
            when '9999-12-31' then cast(getdate() as date)
            else max(date_end) end as date_end,
    datediff(day,
        min(date_begin),
        case max(date_end)
            when '9999-12-31' then cast(getdate() as date)
            else max(date_end) end
    ) as days_difference
from data
where brk = 0
group by peo;

此方法不仅适用于返回最近的分组。 GMB 的答案在其他方面非常相似。