I have a table where multiple users have update access.
Table Point_of_sale ( Brand, Sub_brand, value, start_date, end_date )
If user1 updates the value to $10 and user2 updates the value to $20 without putting end_date on the first record , it creates discrepancy.I need to find out all such values in the table.
Depending on when I’m running this query it should get results for all active records , meaning in below example if I’m running the query in JUN 2021 , the start_date is good for 2 records since it is > 1-JAN-2021 and 5-MAY-2021.
How can I make use of partition by /order by
| Brand | Sub_Brand | Value | START_Date | End_Date |
|---|---|---|---|---|
| Silverware | Spoon | 10 | 1-JAN-2020 | 20-DEC-2020 |
| Silverware | Spoon | 20 | 1-JAN-2021 | |
| Silverware | Spoon | 30 | 5-MAY-2021 |
Expected result of query
| Brand | Sub_Brand | Value | START_Date | End_Date |
|---|---|---|---|---|
| Silverware | Spoon | 20 | 1-JAN-2021 | |
| Silverware | Spoon | 30 | 5-MAY-2021 |
>Solution :
You appear to want to count the NULL values for each brand/sub-brand and then return the NULL values when there are more than two:
SELECT *
FROM (
SELECT p.*,
COUNT(CASE WHEN end_date IS NULL THEN 1 END)
OVER (PARTITION BY brand, sub_brand) AS num_null
FROM point_of_sale p
)
WHERE num_null > 1
AND end_date IS NULL;
Which, for the sample data:
create table Point_of_sale (Brand, Sub_Brand, Value, START_Date, End_Date) AS
SELECT 'Silverware', 'Spoon', 10, DATE '2020-01-01', DATE '2020-12-20' FROM DUAL UNION ALL
SELECT 'Silverware', 'Spoon', 20, DATE '2021-01-01', NULL FROM DUAL UNION ALL
SELECT 'Silverware', 'Spoon', 30, DATE '2021-05-05', NULL FROM DUAL;
Outputs:
| BRAND | SUB_BRAND | VALUE | START_DATE | END_DATE | NUM_NULL |
|---|---|---|---|---|---|
| Silverware | Spoon | 30 | 05-MAY-21 | null | 2 |
| Silverware | Spoon | 20 | 01-JAN-21 | null | 2 |
If you want rows before today then use:
SELECT *
FROM (
SELECT p.*,
COUNT(CASE WHEN end_date IS NULL THEN 1 END)
OVER (PARTITION BY brand, sub_brand) AS num_null
FROM point_of_sale p
WHERE start_date <= SYSDATE
)
WHERE num_null > 1
AND end_date IS NULL;