简体   繁体   中英

How to get distinct closest date in SQL Server?

I don't know how to format?!, but I believe it's easy to understand. I have the following table, lets call it "sales"

|Item|        |Price|        |PriceDate|  
ItemA          801.36         09/23/2011  
ItemA          800.64         09/23/2011  
ItemA          803.55         09/22/2011  
ItemB          4701.36         09/22/2011  
ItemB          1101.36         09/22/2011  
ItemB          4801.36         09/20/2011  
ItemB          401.36         09/22/2011    
ItemC          9601.36         09/21/2011  
ItemC          201.36         09/19/2011  
ItemC          301.36         09/17/2011  

I'm given a date and I need to retrieve the records with the closest date, and only those, for example, if 09/24/2011 is the input, the output should be only the records from the 23rd for item A, 22nd for itemB, and 21st for itemC.

Using SQL Server 2012.

One way to go about it is to calculate the difference between the row's data and the given date by using datediff , assign a rank to each row accordingly and filter by it.

Here I'm using ? as a placeholder for the required date, just switch it with the correct syntax of the language you're using:

SELECT item, price, pricedate
FROM   (SELECT item, price, pricedate,
               RANK() OVER (PARTITION BY item
                            ORDER BY ABS(DATEDIFF(day, pricedate, ?))) AS rk
        FROM   salse) t
WHERE  rk = 1
DECLARE @theTable TABLE (Item VARCHAR(10), price DECIMAL(10,2), priceDate DATE)
INSERT @theTable ( Item, price, priceDate )
VALUES  
('ItemA',801.36,'2011-09-23'),
('ItemA',800.64,'2011-09-23'),
('ItemA',803.55,'2011-09-22'),
('ItemB',4701.36,'2011-09-22'),
('ItemB',1101.36,'2011-09-22'),
('ItemB',4801.36,'2011-09-20'),
('ItemB',401.36,'2011-09-22'),
('ItemC',9601.36,'2011-09-21'),
('ItemC',201.36,'2011-09-19'),
('ItemC',301.36,'2011-09-17')

DECLARE @inputDate DATE
SET @inputDate = '2011-09-24'

SELECT X.Item, X.price, X.priceDate FROM (
SELECT TT.Item, TT.price, TT.priceDate, 
       RANK() OVER (PARTITION BY [Item] 
                          ORDER BY ABS(DATEDIFF(DAY, @inputDate, TT.priceDate))) AS RN
FROM @theTable TT 
) AS X
WHERE RN = 1

 (10 row(s) affected) Item price priceDate ---------- --------------------------------------- ---------- ItemA 801.36 2011-09-23 ItemA 800.64 2011-09-23 ItemB 4701.36 2011-09-22 ItemB 1101.36 2011-09-22 ItemB 401.36 2011-09-22 ItemC 9601.36 2011-09-21

i have the same problem but i found that i can solve it on front end by easier way

/*back end*/
/*(DistinctItem)   select distinct Item from sales*/
/*(saleRecords)    select * from sales order by PriceDate desc*/

/*front end*/
for(var j = 0; j < DistinctItem.length;j++){
  for(var i = 0; i < saleRecords.length;i++){
    if(DistinctItem[j].Item==saleRecords[i].Item){
      if(anyDate>saleRecords[i].PriceDate){
        use saleRecords[i];
        break;
      }
    }
  }
}

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM