Sql 从每个名称的当前日期中获取最后5个日期

Sql 从每个名称的当前日期中获取最后5个日期,sql,sql-server,Sql,Sql Server,嗨,你能帮我查询一下下面的内容吗。我需要每个姓名和日期的最后5个活动日 输入 输出 Name date date2 Active ==== ========== ======= ====== N1 07-30-2018 07-25-2018 Y N1 07-30-2018 07-26-2018 Y N1 07-30-2018 07-28-2018 Y N1 07-30-2018 07-29-2018 Y N1 07-

嗨,你能帮我查询一下下面的内容吗。我需要每个姓名和日期的最后5个活动日

输入

输出

Name date       date2        Active
==== ========== =======      ======
N1   07-30-2018 07-25-2018    Y
N1   07-30-2018 07-26-2018    Y
N1   07-30-2018 07-28-2018    Y
N1   07-30-2018 07-29-2018    Y
N1   07-30-2018 07-30-2018    Y
N1   08-01-2018 07-27-2018    Y
N1   08-01-2018 07-28-2018    Y
N1   08-01-2018 07-29-2018    Y
N1   08-01-2018 07-30-2018    Y 
N1   08-01-2018 08-01-2018    Y
N1   08-02-2018 07-28-2018    Y
N1   08-02-2018 07-29-2018    Y
N1   08-02-2018 07-30-2018    Y
N1   08-02-2018 08-01-2018    Y
N1   08-02-2018 08-02-2018    Y
我正在使用下面的查询来获取此输出,您可以更正它吗

DECLARE @windowStart DATETIME SET @windowStart = '2016-08-01 00:00:00' 
DECLARE @windowEnd DATETIME SET @windowEnd = '2016-09-01 23:00:00'; 

Select a.Wellname,cast(a.timestamp as date) as date1,b.timestamp    --,date2 = dateadd(DAY,-N,timestamp) 
From  TableA --where cast(timestamp as date)>=@windowStart and cast(timestamp as date)<= @windowEnd 
Cross Join (
    Select * 
    from (
        Select distinct m.wellname, cast(m.[timestamp] as date) as timestamp ,Rank() Over ( partition by  m.wellname order by timestamp desc) as Rank 
        from TableA m  
        where m.updown<>'D'  and cast(m.[timestamp] as date) <= (Select cast(T.timestamp as date) from dbo.odr_nd_well_data T where cast(T.timestamp as date)=cast(a.timestamp as date)) and m.wellname in ('WN1','WN2')
        group by m.wellname,m.timestamp
    ) a where a.rank<=5
) B
 --on a.wellname=b.wellname 
where a.wellname='WN1' and cast(a.timestamp as date)>=@windowStart and cast(a.timestamp as date)<= @windowEnd
Order by a.wellname,a.date1,cast(b.timestamp as date)
DECLARE@windowStart DATETIME SET@windowStart='2016-08-01 00:00:00'
声明@windowEnd日期时间集@windowEnd='2016-09-01 23:00:00';
选择a.Wellname,cast(a.timestamp作为日期)作为date1,b.timestamp--,date2=dateadd(DAY,-N,timestamp)

从TableA--where cast(timestamp as date)>=@windowStart和cast(timestamp as date)可能是一个带有特殊计数表的
交叉连接

示例

Select A.*
      ,date2 = dateadd(DAY,-N,date)
 From  YourTable A
 Cross Join (Select Top 5 N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1) B
 Order By name,date,dateadd(DAY,-N,date)
;with cte as (
    Select A.Name
          ,A.Date
          ,date2 = dateadd(DAY,-N,A.date)
          ,A.Active
          ,RN = Row_Number() over (Partition By A.Name,A.Date Order by dateadd(DAY,-N,A.date) desc)
     From  YourTable A
     Cross Join (Select Top 10 N=-1+Row_Number() Over (Order By (Select NULL)) From master..spt_values n1) B
     Left  Join (Select * from YourTable Where Active='N') C on A.Name=C.Name and dateadd(DAY,-N,A.date)=C.date 
     Where A.Active='Y' 
       and C.Name is null
)
Select Name
      ,Date
      ,Date2
      ,Active 
 From  cte
 Where RN <=5
 Order by Name,Date,Date2 
返回

Name    date        date2
N1      2018-08-01  2018-07-27
N1      2018-08-01  2018-07-28
N1      2018-08-01  2018-07-29
N1      2018-08-01  2018-07-30
N1      2018-08-01  2018-07-31
N1      2018-08-02  2018-07-28
N1      2018-08-02  2018-07-29
N1      2018-08-02  2018-07-30
N1      2018-08-02  2018-07-31
N1      2018-08-02  2018-08-01
Name    Date        Date2       Active
N1      2018-07-30  2018-07-26  Y       -- I think you had a typo in the desired results
N1      2018-07-30  2018-07-27  Y
N1      2018-07-30  2018-07-28  Y
N1      2018-07-30  2018-07-29  Y
N1      2018-07-30  2018-07-30  Y
N1      2018-08-01  2018-07-27  Y
N1      2018-08-01  2018-07-28  Y
N1      2018-08-01  2018-07-29  Y
N1      2018-08-01  2018-07-30  Y
N1      2018-08-01  2018-08-01  Y
N1      2018-08-02  2018-07-28  Y
N1      2018-08-02  2018-07-29  Y
N1      2018-08-02  2018-07-30  Y
N1      2018-08-02  2018-08-01  Y
N1      2018-08-02  2018-08-02  Y

作为替代方案,您也可以使用“程序方法”作为以下代码:

declare @tbPrevDates TABLE(
    [name] char (3)
    ,[date] smalldatetime
    ,[date2] smalldatetime
)

declare @count int = -5

WHILE @count<>0
BEGIN
    INSERT @tbPrevDates SELECT [name], [date], DateAdd(d, @count, [date]) FROM YourTable
    SET @count=@Count+1
END 

SELECT * from @tbPrevDates 
ORDER BY
[name],[date],[date2]
declare@tbPrevDates表(
[姓名]字符(3)
,[date]smalldatetime
,[date2]smalldatetime
)
声明@countint=-5
而@count0
开始
插入@tbPrevDates从您的表中选择[name]、[date]、DateAdd(d、@count、[date])
设置@count=@count+1
终止
从@tbPrevDates中选择*
订购人
[姓名],[日期],[日期2]

但是,John Cappelletti的答案对于SQL SERVER来说更加简洁和高级,我的答案有点“通用”…

基于另一个问题中的简化示例。这是实现结果的另一种方法,可以说更简单:

select t1.name, t1.date, t2.date date2, t1.active
from  (
    select distinct name, date from [table] where active = 'Y'
)  t1
cross apply (
     select top 5 date 
     from [table] 
     where active = 'Y' and name = t1.name and date <= t1.date
     order by date desc
) t2
order by name, date, date2
选择t1.name、t1.date、t2.date-date2、t1.active
从(
从[table]中选择不同的名称和日期,其中active='Y'
)t1
交叉应用(
选择前5个日期
从[表]

其中active='Y'和name=t1.name和date看到你的第二篇帖子被关闭了

示例

Select A.*
      ,date2 = dateadd(DAY,-N,date)
 From  YourTable A
 Cross Join (Select Top 5 N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1) B
 Order By name,date,dateadd(DAY,-N,date)
;with cte as (
    Select A.Name
          ,A.Date
          ,date2 = dateadd(DAY,-N,A.date)
          ,A.Active
          ,RN = Row_Number() over (Partition By A.Name,A.Date Order by dateadd(DAY,-N,A.date) desc)
     From  YourTable A
     Cross Join (Select Top 10 N=-1+Row_Number() Over (Order By (Select NULL)) From master..spt_values n1) B
     Left  Join (Select * from YourTable Where Active='N') C on A.Name=C.Name and dateadd(DAY,-N,A.date)=C.date 
     Where A.Active='Y' 
       and C.Name is null
)
Select Name
      ,Date
      ,Date2
      ,Active 
 From  cte
 Where RN <=5
 Order by Name,Date,Date2 

你好,诺迪,谢谢你回复我。我需要在已经存在的过程中包含代码。什么使日期成为活动日期?@Richard我需要每天和每个姓名的最后5个活动日期,我不需要过去5天内不活动的日期。这5个日期是活动日期,可以是最近5个日期中的任何一个。输入中没有7/25的任何数据大概是7月29日,但您将其包含在输出中。您是想生成这些日期,还是有更多的输入数据我们看不到?