Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 获取并过滤SQL中的日期_Sql Server_Date_Select_Where Clause_Gaps And Islands - Fatal编程技术网

Sql server 获取并过滤SQL中的日期

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

我有这张没有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中获得从较旧的日期开始到较新的日期结束的时间传递,如果未定义,则可能是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