Sql server 获取并过滤SQL中的日期
我有这张没有pk的桌子Sql server 获取并过滤SQL中的日期,sql-server,date,select,where-clause,gaps-and-islands,Sql Server,Date,Select,Where Clause,Gaps And Islands,我有这张没有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
| 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中获得从较旧的日期开始到较新的日期结束的时间传递,如果未定义,则可能是9999-12-31,在这种情况下将是实际日期。此表的日期为2017-10-02至9999-12-31 2020/06/23,实际日期 一个问题是,对于下表,它应该只获取最后一行,因为它是该人员在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
对于每个peo,where子句过滤pos为8的最后一系列记录上的表。然后,查询按peo进行聚合,并计算最小开始日期和最大结束日期之间的差值。如果结束日期为“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的答案在其他方面非常相似。未定义时可能是9999-12-31-因此,有人不知道NULL在SQL中的含义,现在您必须处理损坏的数据模型?我想我们在2000年就摆脱了这种情况。我改变了pos比较,将其他职位也包括在内。这解决了我的问题,将获得当前用户位置的天数。如果不存在,则从mytable t1中选择1,其中t1.peo=t.peo,t1.date\u begin>t.date\u end,t1.pos t.pos分组按peo