Here is my approach to solving this problem:
- Associate each search date with a date in the table.
- Use search dates as (optional) group terms.
- Rank dates in descending order, breaking them down into groups.
- Select those that require group term values ββand
rank = 1 .
script:
WITH price_grouped AS ( SELECT date, grp, id, price, dategrp = CASE WHEN date <= '11/30/2009' THEN '11/30/2009' WHEN date <= '12/31/2009' THEN '12/31/2009' /* extend the list of dates here */ END FROM price_table ), price_ranked AS ( SELECT date, grp, id, price, dategrp, rank = RANK() OVER (PARTITION BY grp, dategrp ORDER BY date DESC) FROM price_grouped ) SELECT date, grp, id, price FROM price_ranked WHERE grp IN ('Group1') AND rank = 1
The above solution may not seem very convenient due to the need to repeat each search date twice. An alternative to this could be to define the list of search dates as a separate CTE and, accordingly, assign dates differently:
WITH search_dates (Date) AS ( SELECT '11/30/2009' UNION ALL SELECT '12/31/2009' /* extend the list of dates here */ ), price_grouped AS ( SELECT p.date, p.grp, p.id, p.price, dategrp = MIN(d.Date) FROM price_table p INNER JOIN search_dates d ON p.date <= d.Date GROUP BY p.date, p.grp, p.id, p.price ), price_ranked AS ( SELECT date, grp, id, price, dategrp, rank = RANK() OVER (PARTITION BY grp, dategrp ORDER BY date DESC) FROM price_grouped ) SELECT date, grp, id, price FROM price_ranked WHERE grp IN ('Group1') AND rank = 1
But keep in mind that the first solution is likely to be more effective.