Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.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 T SQL-统计连续3个月内访问的人数_Sql Server_Tsql_Date_Datetime - Fatal编程技术网

Sql server T SQL-统计连续3个月内访问的人数

Sql server T SQL-统计连续3个月内访问的人数,sql-server,tsql,date,datetime,Sql Server,Tsql,Date,Datetime,使用以下数据: 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

使用以下数据:

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'
我需要写一个查询,返回年份&在任何一年中连续三个月访问过的姓名

根据这些数据,我希望看到:

2017 A
2017年D
2018年B
2018年E
老实说,我不知道从哪里开始使用SQL

如果能得到任何帮助,我将不胜感激


谢谢

只需将接下来的两个月加入到数据中,看看数据的去向:

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)
下月单据:

编辑:我的答案只是一个快速的破解,性能非常好,当每个月有多个实例时会出错。
我建议使用这个答案:

您可以使用与
间隙和孤岛
中相同的方法避免连接,或者多次解析整个数据集

按照postgres SQL 9.5.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

2017年12月、2018年1月、2018年2月的情况如何?最初的问题是:我需要写一个查询,返回年份以及在任何一年的任何连续三个月内访问过的姓名。因此,无需在下一页中检查日期year@Isitar这是正确的。访问日期必须在同一日历年内连续3个月内。@Isitar:我使用了你的第二个建议,但这两个建议都有效。注意:我篡改了我的数据,发现如果我连续4个月有名字,年份名称组合会出现两次——如果我连续5个月有名字,会出现3次。。。但是,由于我的测试数据没有显示这种可能性,因此没有对您的解决方案进行思考。谢谢如果在一个月内有多个事件(),并且在连接谓词中使用函数会阻止索引的使用,则会变得疯狂。加入+不使用索引+大量复制结果=效率严重低下。计数器会在12月后重置吗?@Salman:是的。是的。谢谢。2月1日、3月31日、4月30日的顺序算吗?你实际上只是在寻找3个连续的日历月,即使两个事件距离相隔两个月还有一天?@MatBalie:是的。即使他们相隔两个月只有一天——即使他们相隔一天【2月28日,3月1日】。只要是在连续三个日历月内。
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