2

鉴于此表:

替代文字

如何获取每组 ID_Number 的每个 status_date 之间的日期差异(以天为单位)?换句话说,我需要找到给定 ID_Number 的每个状态的经过天数。

一些事情要知道:

  • 所有 ID_Number 都会有一个 received_date,它应该是每个 ID_Number 的最早日期(但应用程序不强制执行)
  • 对于每个 ID_Number 都会有一个状态,其对应的 status_date 是 ID_Number 获得该特定状态的日期。
  • 状态列不一定每次都以相同的顺序排列(应用程序不强制)
  • 所有 ID_Number 都将有一个 closed_date,它应该是最晚的日期(但应用程序不强制执行)

示例输出:因此对于 ID_Number 2001,第一个日期 (received_date) 是 2009-05-02,而您遇到的下一个日期的状态为“open”并且是 2009-05-02,因此经过的天数为 0。继续遇到的下一个日期是 2009 年 5 月 10 日,状态为“投资”,经过的天数是从前一个日期算起的 8 天。遇到的下一个日期是 2009-07-11,经过的天数是从前一个日期算起的 62 天。

编辑添加:

是否可以将经过的天数作为此表/视图上的一列?我还忘了补充说这是 SQL Server 2000。

4

3 回答 3

2

我的理解是,您需要相同id的第一个status_date和下一个status_date之间的差异,依此类推,直到closed_date。

这仅适用于 SQL 2005 及更高版本。

;with test as (
    select 
        key,
        id_number,
        status,
        received_date,
        status_date,
        closed_date,
        row_number() over (partition by id order by status_date, key ) as rownum
    from @test
    )
select 
    t1.key,
    t1.id_number,
    t1.status,
    t1.status_date,
    t1.received_date,
    t1.closed_date,
    datediff(d, case when t1.rownum = 1 
                then t1.received_date
                else    
                    case when t2.status_date is null 
                        then t1.closed_date 
                        else t2.status_date 
                    end
            end,
            t1.status_date
         ) as days
from test t1
left outer join test t2
on t1.id = t2.id
    and t2.rownum = t1.rownum - 1

此解决方案适用于 SQL 2000,但我不确定性能如何:

select *,
    datediff(d,
        case when prev_date is null
            then closed_date
            else prev_date
        end,
        status_date )
from ( 
    select *,
        isnull( ( select top 1 t2.status_date 
          from @test t2
          where t1.id_number = t2.id_number
            and t2.status_date < t1.status_date
          order by t2.status_date desc
          ),received_date) as prev_date 
    from @test t1
) a
order by id_number, status_date

注意:将@Test 表替换为您的表的名称。

于 2010-01-30T00:16:54.297 回答
0

一些示例输出确实会有所帮助,但这是对您的意思的猜测,假设您想要每个 ID_Number/Status 组合的信息:

select ID_Number, Status, EndDate - StartDate as DaysElapsed
from (
    select ID_Number, Status, min(coalesce(received_date, status_date)) as StartDate, max(coalesce(closed_date, status_date)) as EndDate
    from Table1
    group by ID_Number, Status
) a
于 2010-01-30T00:04:54.100 回答
0

棘手的一点是确定先前的状态并将其与当前状态放在同一行。Key如果和之间存在相关性StatusDate(即Key(x) > Key(y)总是暗示StatusDate(x) >= StatusDate(y)) ,它会被简化一点。不幸的是,情况似乎并非如此。

PS:我假设Key是您桌子上的唯一标识符;你没有说任何其他说明。

SELECT  Key,
        ID_Number, 
        (
        SELECT  TOP 1 Key
        FROM    StatusUpdates prev
        WHERE   (prev.ID_Number = cur.ID_Number)
            AND (   (prev.StatusDate < cur.StatusDate)
                OR  (   prev.StatusDate = cur.StatusDate
                    AND prev.Key < cur.Key
                    )
                )
        ORDER BY StatusDate, Key /*Consider index on (ID_Number, StatusDate, Key)*/
        ) PrevKey
FROM    StatusUpdates cur

一旦您以此为基础,就很容易从当前或以前的 StatusUpdate 中推断出您需要的任何其他信息。例如

SELECT  c.*,
        p.Status AS PrevStatus,
        p.StatusDate AS PrevStatusDate,
        DATEDIFF(d, c.StatusDate, p.StatusDate) AS DaysElapsed
FROM    (
        SELECT  Key,
                ID_Number, 
                Status,
                SattusDate,
                (
                SELECT  TOP 1 Key
                FROM    StatusUpdates prev
                WHERE   (prev.ID_Number = cur.ID_Number)
                    AND (   (prev.StatusDate < cur.StatusDate)
                        OR  (   prev.StatusDate = cur.StatusDate
                            AND prev.Key < cur.Key
                            )
                        )
                ORDER BY StatusDate, Key
                ) PrevKey
        FROM    StatusUpdates cur
        ) c
        JOIN StatusUpdates p ON
            p.Key = c.PrevKey
于 2010-01-30T08:17:26.707 回答