需要一个SQL Server查询,根据给定的日期获取3行的集合

时间:2014-08-17 01:36:34

标签: sql sql-server

我需要根据给定的日期(必须是此日期)获得每组3行,但我希望这些行基于此日期:

1 ( row where the date from the date column is the next date after given date )   
0 ( row where the date is the closest date prior to the date given )  
-1 ( prior to the date at 0 )

并添加一个包含相对数字的列。

**相同​​名称和项目的日期永远不会重复。

例如,一组行:

Row ID, Name, Item, Number, Date   
1       Andy, Item1, 12030, 2014-06-30  
2       Andy, Item1, 62030, 2014-03-31  
3       Andy, Item1, 30300, 2013-12-31  
4       Andy, Item1, 40030, 2013-10-31  
5       Andy, Item1, 50030, 2013-08-30
6       John, Item2, 50240, 2014-04-30
7       John, Item2, 41400, 2014-03-31
8       John, Item2, 40509, 2014-01-31
9       Andy, Item2, 24004, 2014-03-31
10      Andy, Item2, 20144, 2013-12-31   
11      Andy, Item2, 20450, 2013-09-30   
12      Andy, Item2, 25515, 2013-06-30

如果我将2014-03-15作为日期并搜索'Andy',我希望:

 Row ID, Item,   Date,        Relative Date
 2,      Item1,  2014-03-31,  1  
 3,      Item1,  2013-12-31,  0  
 4,      Item1,  2013-10-31,  -1
 9,      Item2,  2014-03-31,  1
10,      Item2,  2013-12-31,  0   
11,      Item2,  2013-09-30,  -1         

这就是我正在使用的,如果有必要,我没有问题切换:

DATEDIFF( quarter, 2014-03-31, date ) 

date BETWEEN DATEADD( quarter, -1, '20140315' ) AND   
DATEADD( day, 1 ( DATEADD ( quarter, 2, '20140315' ) )  

返回:

 Row ID, Item,   Date,        Relative Date
 2,      Item1,  2014-06-30,  1  
 3,      Item1,  2014-03-31,  0  
 4,      Item1,  2013-12-31,  -1
 9,      Item2,  2014-03-31,  0
10,      Item2,  2013-12-31,  -1   

在没有日期数学的情况下,有更好的方法吗?我不认为我可以完成我想要的日期数学,因为很难捕获我需要的3行。

也许是row_number()?

1 个答案:

答案 0 :(得分:1)

像...一样的东西。

CREATE TABLE #TEMP
(
    RowID int
    , Name varchar(25)
    , Item varchar(25)
    , Number int
    , [Date] datetime
)

INSERT INTO #TEMP
VALUES (1, 'Andy', 'Item1', 12030, '2014-06-30T00:00:00')  
, (2, 'Andy', 'Item1', 62030, '2014-03-31T00:00:00')  
, (3, 'Andy', 'Item1', 30300, '2013-12-31T00:00:00')  
, (4, 'Andy', 'Item1', 40030, '2013-10-31T00:00:00')  
, (5, 'Andy', 'Item1', 50030, '2013-08-30T00:00:00')  

DECLARE @Date datetime 
SET @Date = '2014-03-15T00:00:00'

CREATE TABLE #NameItem
(
    ID int identity(1,1)
    , Name varchar(25)
    , Item varchar(25)
)

CREATE TABLE #Results
(
    NIID int
    , RowID int
    , [Date] datetime
    , RelativeDate int
)

INSERT INTO #NameItem
(Name, Item)
SELECT DISTINCT Name, Item
FROM #TEMP a

INSERT INTO #Results
(NIID, RowID, [Date], RelativeDate)
SELECT a.ID, b.RowID, b.[Date], b.RelativeDate
FROM #NameItem a
CROSS APPLY (
                SELECT TOP 1 z.RowID, z.[Date], 1 AS RelativeDate
                FROM #TEMP z
                WHERE z.Name = a.Name
                AND z.Item = a.Item
                AND [Date] > @Date
                ORDER BY [Date]
            ) b

INSERT INTO #Results
(NIID, RowID, [Date], RelativeDate)
SELECT a.ID, b.RowID, b.[Date], b.RelativeDate
FROM #NameItem a
CROSS APPLY (
                SELECT TOP 1 z.RowID, z.[Date], 0 AS RelativeDate
                FROM #TEMP z
                WHERE z.Name = a.Name
                AND z.Item = a.Item
                AND [Date] < @Date
                ORDER BY [Date] DESC
            ) b

; with cte_0 as
(
    SELECT a.NIID, a.[Date]
    FROM #Results a
    WHERE a.RelativeDate = 0
)

INSERT INTO #Results
(NIID, RowID, [Date], RelativeDate)
SELECT b.ID, c.RowID, c.[Date], c.RelativeDate
FROM cte_0 a
INNER JOIN #NameItem b
    ON a.NIID = b.ID
CROSS APPLY (
                SELECT TOP 1 z.RowID, z.[Date], -1 AS RelativeDate
                FROM #TEMP z
                WHERE z.Name = b.Name
                AND z.Item = b.Item
                AND z.[Date] < a.[Date]
                ORDER BY [Date] DESC
            ) c


SELECT a.Name, a.Item, b.RowID, b.[Date], b.RelativeDate
FROM #NameItem a
INNER JOIN #Results b
    ON a.ID = b.NIID
ORDER BY a.ID, b.RelativeDate DESC 

DROP TABLE #NameItem
DROP TABLE #Results
DROP TABLE #TEMP