我正在尝试比较同一表中的数据行

I am trying to compare rows of data within the same table

提问人:DJT 提问时间:11/17/2023 最后编辑:Thom ADJT 更新时间:11/17/2023 访问量:106

问:

我有一个表,其中包含带有 id 和录取日期的行 - 我需要比较日期并获取彼此相隔 30 天内的录取日期数据

ID        Date
--------------------
1         05/01/2023
2         06/12/2023
2         05/17/2023
2         08/01/2023
3         06/01/2023
3         06/15/2023
3         07/10/2023

我已经创建了带有日期的不同 ID 的视图(但无法通过创建方式进行排序)我读取了带有联接视图的相同表,但我得到了重复项。

谁能帮忙?

sql-server

评论

2赞 Jiji 11/17/2023
您能否用示例数据和预期结果编辑您的问题?最小可重复示例
0赞 amdixon 11/17/2023
表的名称是什么?
0赞 Hamlet Hakobyan 11/17/2023
您已提供数据。期望的结果在哪里?
0赞 Xedni 11/17/2023
SQL Server Management [Studio] 是一个 IDE,而不是数据库引擎,因此与您的问题无关紧要。最好指定正在运行的 SQL Server 版本。您可以通过将运行以下内容的结果粘贴到您的实例来获得该结果:select @@version

答:

0赞 T N 11/17/2023 #1

如果您只想列出这些录取与附近的匹配项,则可以使用谓词。EXISTS()

SELECT D.*
FROM Data D
WHERE EXISTS (
    SELECT D2.*
    FROM Data D2
    WHERE D2.ID = D.ID
    AND D2.Date BETWEEN DATEADD(day, -30, D.Date) AND DATEADD(day, 30, D.Date)
    AND D2.Date <> D.Date -- Using a unique admission ID here would be better
)
ORDER BY D.ID, D.Date

结果:

编号 日期
2 2023-05-17
2 2023-06-12
3 2023-06-01
3 2023-06-15
3 2023-07-10

如果您还想包括入院前或入院后最接近的细节,则可以使用 .an 就像 a 对子选择。OUTER APPLY(SELECT TOP 1 ... ORDER BY ...)OUTER APPLYLEFT JOIN

SELECT D.*, PRIOR.Date as PriorDate, NEXT.Date as NextDate
FROM Data D
OUTER APPLY (
    SELECT TOP 1 D2.*
    FROM Data D2
    WHERE D2.ID = D.ID
    AND D2.Date >= DATEADD(day, -30, D.Date)
    AND D2.Date < D.Date
    ORDER BY D2.Date DESC
) PRIOR
OUTER APPLY (
    SELECT TOP 1 D2.*
    FROM Data D2
    WHERE D2.ID = D.ID
    AND D2.Date > D.Date
    AND D2.Date <= DATEADD(day, 30, D.Date)
    ORDER BY D2.Date
) NEXT
-- WHERE (PRIOR.Date IS NOT NULL OR NEXT.Date IS NOT NULL)
ORDER BY D.ID, D.Date

结果:

编号 日期 PriorDate(上一个日期) 下一个日期
1 2023-05-01
2 2023-05-17 2023-06-12
2 2023-06-12 2023-05-17
2 2023-08-01
3 2023-06-01 2023-06-15
3 2023-06-15 2023-06-01 2023-07-10
3 2023-07-10 2023-06-15

也可以使用 和 窗口函数。LAG()LEAD()

SELECT D.*
FROM (
    SELECT *,
        LAG(Date) OVER(PARTITION BY ID ORDER BY Date) AS PriorDate,
        LEAD(Date) OVER(PARTITION BY ID ORDER BY Date) AS NextDate
    FROM Data
) D
WHERE DATEDIFF(day, D.PriorDate, D.Date) <= 30
OR DATEDIFF(day, D.Date, D.NextDate) <= 30
ORDER BY D.ID, D.Date

结果:

编号 日期 PriorDate(上一个日期) 下一个日期
2 2023-05-17 2023-06-12
2 2023-06-12 2023-05-17 2023-08-01
3 2023-06-01 2023-06-15
3 2023-06-15 2023-06-01 2023-07-10
3 2023-07-10 2023-06-15

请参阅此 db<>fiddle

0赞 Error_2646 11/17/2023 #2

这只是一个提示。希望有一个例子来说明如何在这里列出你的问题以获得更好的答案。dbfiddle 笔记本总是很可爱。https://dbfiddle.uk/PahXd98E

一个可重现的例子可以澄清许多细微差别。我可以用 5 种不同的方式解释您的问题和预期结果。

摘要:这将为您提供所有ID,对于相同的ID,N行数。对于具有相同 ID 且未来 30 天小于或等于 30 天的_date的每条记录,一个记录。

输入:

id  _date
1   2023-05-01
2   2023-06-12
2   2023-05-17
2   2023-05-15
2   2023-08-01
3   2023-06-01
3   2023-06-15
3   2023-07-10

帮助重现的代码:

create table id_date (
  id integer,
  _date date
);

insert into id_date (id,_date) values (1, cast('2023-05-01' as date));
insert into id_date (id,_date) values (2, cast('2023-06-12' as date));
insert into id_date (id,_date) values (2, cast('2023-05-17' as date));
insert into id_date (id,_date) values (2, cast('2023-05-15' as date));
insert into id_date (id,_date) values (2, cast('2023-08-01' as date));
insert into id_date (id,_date) values (3, cast('2023-06-01' as date));
insert into id_date (id,_date) values (3, cast('2023-06-15' as date));
insert into id_date (id,_date) values (3, cast('2023-07-10' as date));

预期:

select t1.id,
       t1._date as original_date,
       t2._date as later_date_within_30_days
  from id_date t1
 inner
  join id_date t2 
    on t1.id = t2.id 
   and t2._date > t1._date -- strict inequality so avoid the record picking
                             -- up itself.
   and t2._date <= DATEADD(day, 30, t1._date)

结果

id  original_date   later_date_within_30_days
2   2023-05-17      2023-06-12
2   2023-05-15      2023-05-17
2   2023-05-15      2023-06-12
3   2023-06-01      2023-06-15
3   2023-06-15      2023-07-10
-1赞 Saikat 11/17/2023 #3

下面是使用 SQL Server 的解决方案。虽然你的要求不是很清楚,但我还是尝试并想出了一些可能有助于你得到答案的东西。first_id , second_id , first_date 在这里second_date说的是两个 id 及其日期之间的比较。如果这是你要找的,请告诉我。

    with prepare_data as
    (
    select a.id as first_id , b.id as second_id ,  
           a.admit_date as first_date , b.admit_date as second_date ,
           abs(DATEDIFF(day,a.admit_date,b.admit_date)) as diff  from
        (
            select id , convert(date , dt , 101) as admit_date from admit_dt
        ) as a , 
        (
            select id , convert(date , dt , 101) as admit_date from admit_dt
        ) as b
    where a.id <> b.id and abs(DATEDIFF(day,a.admit_date,b.admit_date))  <= 30
    )
    select 
           distinct case when first_id < second_id then first_id else second_id end as first_id ,
           case when first_id > second_id then first_id else second_id end as second_id ,
           case when first_date < second_date then first_date else second_date end as first_date , 
           case when first_date > second_date then first_date else second_date end as second_date ,  
           diff
    from prepare_data;

enter image description here