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

时间:2018-09-18 15:53:19

标签: sql sql-server

HI您能帮我查询以下结果吗?我需要每个名称和每个日期的最近5天有效期。

输入

Name date          Active
==== ====         ========
N1   07-30-2018      Y
N1   07-31-2018      N
N1   08-01-2018      Y
N1   08-02-2018      Y

输出

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)

4 个答案:

答案 0 :(得分:3)

也许一个CROSS JOIN带有临时提示表

示例

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)

返回

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

答案 1 :(得分:1)

Saw your second post was closed. Take a peek at

Example

;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 

Returns

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

答案 2 :(得分:0)

基于另一个问题中的简化示例。这是获得结果的替代方法,而且可能更简单:

ID - ALIAS 
1 - PIPPO
2 - PLUTO

这里我不清楚的是如何处理7/25到7/29之间的日期。这些日期出现在示例输出中,但没有出现在输入中。您是否要基于数字或日历表(假设它们会一直处于活动状态)生成这些日期,是否有更多未共享的输入数据,或者您想要更少的输出?假设存在更多未共享的输入,则写出此答案。

答案 3 :(得分:-1)

或者,您也可以将“过程方法”用作以下代码:

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]

但是,约翰·卡佩莱蒂(John Cappelletti)的答案相对于SQL SERVER更紧凑,更高级,我的答案有点“泛型”……