I have a table of data:
ProductNum | ProductVariation | Past_Price | Current_Price | Order_Date
------------ ------------------ ------------ --------------- ---------------------
1 33 96.05 100.10 2014-01-01 00:00:00
1 33 97.65 100.10 2014-12-03 12:34:52
1 33 98.98 100.10 2015-01-02 05:50:32
1 33 99.98 100.10 2016-03-02 06:50:43
1 33 100.01 100.10 2016-12-12 06:05:43
1 33 100.05 100.10 2017-01-02 05:34:43
I was wondering if its possible to query for the rows such that we get the row that has the closest date to Dec 31,{Year} ?
So the output would be :
ProductNum | ProductVariation | Past_Price | Current_Price | Order_Date
------------ ------------------ ------------ --------------- ---------------------
1 33 98.98 100.10 2015-01-02 05:50:32
1 33 99.98 100.10 2016-03-02 06:50:43
1 33 100.01 100.10 2017-01-02 05:34:43
Each order being the closest to Dec 31,{Year} for Years: 2014,2015,2016
You can sort by the date difference and get the top 1 row for each year.
For SqlServer :
DECLARE @year2014 datetime2 = '2014-12-31 12:00:00';
DECLARE @year2015 datetime2 = '2015-12-31 12:00:00';
DECLARE @year2016 datetime2 = '2016-12-31 12:00:00';
select * from (
select top(1) * from products
order by abs(datediff(second, @year2014, Order_Date))
) as p
union all
select * from (
select top(1) * from products
order by abs(datediff(second, @year2015, Order_Date))
)as p
union all
select * from (
select top(1) * from products
order by abs(datediff(second, @year2016, Order_Date))
) as p
Change the time of the 31st of December as you like.
For MySql :
set @year2014 = '2014-12-31 12:00:00';
set @year2015 = '2015-12-31 12:00:00';
set @year2016= '2016-12-31 12:00:00';
select * from (
select * from products
order by abs(TIMESTAMPDIFF(second, @year2014, Order_Date)) limit 1
) as p
union all
select * from (
select * from products
order by abs(TIMESTAMPDIFF(second, @year2015, Order_Date)) limit 1
)as p
union all
select * from (
select * from products
order by abs(TIMESTAMPDIFF(second, @year2016, Order_Date)) limit 1
) as p
Get row_number()
s for each year ordered by the absolute datediff()
between the order date and 31-12 of the year. Then select all where one of the row numbers equals 1
.
SELECT *
FROM (SELECT *,
row_number() OVER (ORDER BY abs(datediff(second, '2014-12-31', t.order_date))) rn2014,
row_number() OVER (ORDER BY abs(datediff(second, '2015-12-31', t.order_date))) rn2015,
row_number() OVER (ORDER BY abs(datediff(second, '2016-12-31', t.order_date))) rn2016
FROM elbat t) x
WHERE 1 IN (x.rn2014,
x.rn2015,
x.rn2016);
You can use this. This will avoid hard coding years and copying pasting unions.
declare @currDate datetime;
select @currDate = '12/31/2019';
while @currDate > '12/31/2013'
begin
select *
from Product
where abs(datediff(second, OrderDate, @currDate))
= (select min(
abs(datediff(second, OrderDate, @currDate))
)
from Product )
select @currDate = dateadd(year,-1,@currDate);
end
I used the following fiddle:
create table Product (ProdNum int, ProdVar int, PastPrice decimal, CurrentPrice decimal, OrderDate datetime);
insert into Product values (1, 33, 96.05, 100.10, '2014-01-01 00:00:00');
insert into Product values (1, 33, 97.65, 100.10, '2014-12-03 12:34:52');
insert into Product values (1, 33, 98.98, 100.10, '2015-01-02 05:50:32');
insert into Product values (1, 33, 99.98, 100.10, '2016-03-02 06:50:43');
insert into Product values (1, 33, 100.01, 100.10, '2016-12-12 06:05:43');
insert into Product values (1, 33, 100.05, 100.10, '2017-01-02 05:34:43');
You seem to actually want the first date after the end of the year:
select top (1) with ties t.*
from t
order by row_number() over (partition by year(order_date) order by order_date asc);
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.