There are 2 tables -
- Sales table with details of order_number, item_number and sale_date.
- Promotions table with details of item_number, promotion_start_date and promotion_end_date.
Promotions run all through the year over a range of days. Need is to extract list of items sold when no promotion was running.
Need to extract only the order numbers between
- "first promotion_end_date" and "second promotion_start_date" then
- "second promotion_end_date" and "third promotion_start_date" then
- "third promotion_end_date" and "fourth promotion_start_date" and so on.
Sample tables are as follows -
1) Promotions table : ( When promotion_end_date is 'Null', promotion is still 'ACTIVE')
item_number | promotion_start_date | promotion_end_date |
---|---|---|
ABC0001 | 12-31-2020 | 01-19-2021 |
ABC0001 | 03-01-2021 | 03-31-2021 |
ABC0005 | 02-05-2021 | 03-01-2021 |
ABC0002 | 06-01-2021 | 07-31-2021 |
ABC0001 | 09-31-2021 | 11-05-2021 |
ABC0001 | 11-08-2021 | Nil |
2) Sales Table :
order_number | item_number | sale_date |
---|---|---|
110000011 | ABC0001 | 01-18-2021 |
110000012 | ABC0001 | 01-31-2021 |
110000013 | ABC0002 | 06-30-2021 |
110000014 | ABC0001 | 07-31-2021 |
110000015 | ABC0005 | 04-05-2021 |
110000016 | ABC0001 | 10-05-2021 |
110000017 | ABC0001 | 12-01-2021 |
110000018 | ABC0002 | 08-30-2021 |
110000019 | ABC0001 | 04-01-2021 |
110000020 | ABC0001 | 07-30-2021 |
110000021 | ABC0005 | 02-28-2021 |
110000022 | ABC0001 | 11-06-2021 |
3) Expected Result :
order_number | item_number | sale_date |
---|---|---|
110000012 | ABC0001 | 01-31-2021 |
110000014 | ABC0001 | 07-31-2021 |
110000015 | ABC0005 | 04-05-2021 |
110000017 | ABC0001 | 12-01-2021 |
110000018 | ABC0002 | 08-30-2021 |
110000019 | ABC0001 | 04-01-2021 |
110000020 | ABC0001 | 07-30-2021 |
110000022 | ABC0001 | 11-06-2021 |
CodePudding user response:
There are many ways to solve this kind of problem but I generally prefer NOT EXISTS
:
SELECT order_number, item_number, sale_date
FROM dbo.Sales AS s
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Promotions AS p
WHERE s.item_number = p.item_number
AND s.sale_date >= p.promotion_start_date
AND s.sale_date <= COALESCE(p.promotion_end_date, GETDATE())
);
I think the trickiest part here is substituting the end date with a valid point in time when the promotion is ongoing.
- Example db<>fiddle which shows how we love to see table structure and sample data and also corrects September 31st.