У меня есть набор данных, из которого я пытаюсь удалить записи при следующих условиях:

Если у практики есть несколько записей с одной и той же датой, и хотя бы одна запись имеет причину «L&B», тогда я хочу, чтобы все практиды для этой даты были удалены.

DECLARE t table(practid int, statusdate date, reason varchar(100)

INSERT INTO t VALUES (1, '2018-03-01', 'L&B'),
                     (1, '2018-03-01', 'NULL'),
                     (1, '2018-04-01, 'R&D'),
                     (2, '2018-05-01, 'R&D'),
                     (2, '2018-05-01, 'R&D'),
                     (2, '2018-03-15', NULL),
                     (2, '2018-03-15', 'R&D),
                     (3, '2018-07-01, 'L&B)

С этим набором данных я хотел бы получить следующий результат:

PractId  StatusDate   Reason
1         2018-04-01   R&D
2         2018-05-01   R&D
2         2018-05-01   R&D
2         2018-03-15    NULL
2         2018-03-15   R&D

Я попытался решить эту проблему с помощью оконной функции, но застрял:

SELECT *, ROW_NUMBER() OVER
    (PARTITION BY practid, statusdate, CASE WHEN reason = 'L&B' THEN 0 ELSE 1 END) AS rn
FROM table

Из моего запроса я не могу понять, как сохранить Practid = 2, так как я хотел бы сохранить все записи.

1
jackstraw22 24 Сен 2018 в 19:31

2 ответа

Лучший ответ

Чтобы продолжить ваш текущий подход, мы можем использовать COUNT в качестве аналитической функции. Мы можем подсчитать появление причины L&B в каждом окне practid/statusdate, а затем сохранить только те группы, в которых эта причина никогда не встречается.

SELECT practid, statusdate, reason
FROM
(
    SELECT *,
        COUNT(CASE WHEN reason = 'L&B' THEN 1 END) OVER
            (PARTITION BY practid, statusdate) cnt
    FROM yourTable
) t
WHERE cnt = 0;

демонстрация

2
Tim Biegeleisen 24 Сен 2018 в 16:51

Вы можете попробовать использовать not exists в подзапросе.

 Select *
 from t t1
 where not exists (
     select 1 
     from t tt
     where tt.reason = 'L&B' and t1.statusdate = tt.statusdate
 )

sqlfiddle

2
D-Shih 24 Сен 2018 в 16:39