提问人:DJT 提问时间:11/17/2023 最后编辑:Thom ADJT 更新时间:11/17/2023 访问量:106
我正在尝试比较同一表中的数据行
I am trying to compare rows of data within the same table
问:
我有一个表,其中包含带有 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 的视图(但无法通过创建方式进行排序)我读取了带有联接视图的相同表,但我得到了重复项。
谁能帮忙?
答:
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 APPLY
LEFT 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;
评论
select @@version