I need to get 3 rows per set based on a date given (must be this date) but I want the rows to be based on this date as:
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 )
And add a column with the relative number.
** The dates for the same name and item will never repeat.
For example, a set of rows:
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
If I have 2014-03-15 as the date and search for 'Andy', I expect:
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
This is what I'm using which I have no issues switching if necessary:
DATEDIFF( quarter, 2014-03-31, date )
date BETWEEN DATEADD( quarter, -1, '20140315' ) AND
DATEADD( day, 1 ( DATEADD ( quarter, 2, '20140315' ) )
which returns:
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
Is there a better way of doing this without date math? I don't think I can accomplish exactly what I want with date math because it's hard to capture the exact 3 rows I need.
Perhaps something with row_number()?
Something like...
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.