Home > Back-end >  SQL Query conditional on date column
SQL Query conditional on date column

Time:05-11

I have a table with historical option prices, and I would like to select for each day the contract(s) that have the closest expiration date. Below is a min examples:

Date         ExpDate   Unique Contract ID
1/1/2022     2/1/2022   1
1/1/2022     3/1/2022   2
2/1/2022     3/1/2022   3
2/1/2022     4/1/2022   4

For this table I would like to obtain this:

Date         ExpDate   Unique Contract ID
1/1/2022     2/1/2022   1
2/1/2022     3/1/2022   3

Not sure if this could be done with maybe a groupby? The query below isn't working as it won't allow me to select all the columns for some reason:

SELECT *, MIN(ExpDate) FROM table_name GROUP BY Date

CodePudding user response:

We can accomplish this with ROWNUMBER by getting the difference between the dates:

with ordered as
(
    select Date
        , ExpDate
        , [Unique Contract ID]
        , ROW_NUMBER() over (partition by Date order by DATEDIFF(dd, Date, ExpDate)) rn
    from tbl
)
select Date
    , ExpDate
    , [Unique Contract ID]
from ordered o
where o.rn = 1

This was done in T-SQL since you didn't provide a DBMS.

CodePudding user response:

In Oracle, and other RDBMS that support analytic functions, you can use:

SELECT "DATE", ExpDate, ID
FROM   (
  SELECT t.*,
         RANK() OVER (PARTITION BY "DATE" ORDER BY ExpDate - "DATE") AS rnk
  FROM   table_name t
) t
WHERE  rnk = 1;

Which, for the sample data:

CREATE TABLE table_name ("DATE", ExpDate, ID) AS
SELECT DATE '2022-01-01', DATE '2022-01-02', 1 FROM DUAL UNION ALL
SELECT DATE '2022-01-01', DATE '2022-01-03', 2 FROM DUAL UNION ALL
SELECT DATE '2022-01-02', DATE '2022-01-03', 3 FROM DUAL UNION ALL
SELECT DATE '2022-01-02', DATE '2022-01-04', 4 FROM DUAL;

Outputs:

DATE EXPDATE ID
2022-01-02 00:00:00 2022-01-03 00:00:00 3
2022-01-01 00:00:00 2022-01-02 00:00:00 1

db<>fiddle here

  • Related