具有以下数据:
Declare @t Table
(
Name Varchar(1),
VisitDate Date
)
Insert Into @t select 'A','2017-01-05'
Insert Into @t select 'A','2017-03-05'
Insert Into @t select 'A','2017-04-05'
Insert Into @t select 'A','2017-05-05'
Insert Into @t select 'A','2017-08-05'
Insert Into @t select 'B','2017-03-05'
Insert Into @t select 'C','2017-01-05'
Insert Into @t select 'C','2017-02-05'
Insert Into @t select 'C','2017-04-05'
Insert Into @t select 'D','2017-01-05'
Insert Into @t select 'D','2017-02-05'
Insert Into @t select 'D','2017-03-05'
Insert Into @t select 'D','2017-06-05'
Insert Into @t select 'B','2018-01-05'
Insert Into @t select 'B','2018-02-05'
Insert Into @t select 'B','2018-03-05'
Insert Into @t select 'E','2018-01-05'
Insert Into @t select 'E','2018-02-05'
Insert Into @t select 'E','2018-03-05'
Insert Into @t select 'E','2018-06-05'
我需要编写一个查询,该查询将返回任何一年中连续三个月中具有VisitDates的Year&Names。
基于数据,我希望看到:
2017 A
2017 D
2018 B
2018 E
说实话,我不知道从哪里开始使用SQL。
我将不胜感激。
谢谢!
答案 0 :(得分:1)
通过使用与gaps-and-islands
中相同的方法,可以避免联接或多次分析整个数据集。
http://rextester.com/SYHJ40676
WITH
sequenced AS
(
SELECT
Name,
YEAR(VisitDate) AS VisitYear,
MONTH(VisitDate) AS VisitMonth,
ROW_NUMBER()
OVER (PARTITION BY Name, YEAR(VisitDate)
ORDER BY MONTH(VisitDate)
)
AS MonthSequenceID
FROM
@t
GROUP BY
Name,
YEAR(VisitDate),
MONTH(VisitDate)
)
SELECT DISTINCT
Name,
VisitYear
FROM
sequenced
GROUP BY
Name,
VisitYear,
VisitMonth - MonthSequenceID
HAVING
COUNT(*) >= 3
答案 1 :(得分:0)
只需将接下来的两个月加入到数据中,然后查看数据的去向:
SELECT DATEPART(year, m1.VisitDate), m1.Name
FROM @t m1
JOIN @t m2 on m2.Name = m1.Name AND DATEPART(month, m2.VisitDate) = DATEPART(month, m1.VisitDate) + 1
JOIN @t m3 on m3.Name = m1.Name AND DATEPART(month, m3.VisitDate) = DATEPART(month, m1.VisitDate) + 2
由于在评论中被问到如何解决一年重叠的问题,所以这应该可行:
SELECT DATEPART(year, m1.VisitDate), m1.Name
FROM @t m1
JOIN @t m2 on m2.Name = m1.Name AND EOMONTH(m1.VisitDate,1) = EOMONTH(m2.VisitDate)
JOIN @t m3 on m3.Name = m1.Name AND EOMONTH(m1.VisitDate,2) = EOMONTH(m3.VisitDate)
关于EOMONTH的文档:https://docs.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql?view=sql-server-2017
edit:我的答案只是快速破解,并且性能很差,每月有多个实例时会出错。 我建议使用以下答案:https://stackoverflow.com/a/52669713/4903754
答案 2 :(得分:0)
首先,我创建了连续几个月的标志,并使用该标志检索了所需的data.lag(),lead()
对于我使用的lag(),lead()
函数,我们需要比较它们连续或不连续的日期。
with temp as (
select name,visitdate,
coalesce(lag(visitdate) over (partition by name order by visitdate),lead(visitdate) over (partition by name order by visitdate))check1,
coalesce(lead(visitdate) over (partition by name order by visitdate),lag(visitdate) over (partition by name order by visitdate)) check2
from TT
order by 1
),
t2 as (
select name,
case
when
(DATE_PART('year', visitdate::date) - DATE_PART('year', check1::date)) * 12 +
(DATE_PART('month', visitdate::date) - DATE_PART('month', check1::date))=1
or
(DATE_PART('year', check2::date) - DATE_PART('year', visitdate::date)) * 12 +
(DATE_PART('month', check2::date) - DATE_PART('month', visitdate::date))=1
then 1 else 0
end as flag
from temp)
select name ,count(1) from t2 where flag=1 group by name having count(1)>=3