У меня есть следующий SQL для получения строк с наивысшим (максимальным) и 2-м наивысшими датами. В данных есть несколько случаев, когда единственной разницей в «СТАРОЙ СТРОКЕ» и «НОВОЙ СТРОКЕ» является дата вступления в силу. То, что я хотел бы сделать, это показать только старые и новые строки для EMPLID, где BANK_CD и / или ACCOUNT_NUM отличаются между «старыми» и «новыми» строками.
WITH CTE AS (
SELECT A.EMPLID
, C.VENDOR_ID
, B.FIRST_NAME
, B.LAST_NAME
, A.BANK_CD
, A.ACCOUNT_NUM
, A.ACCOUNT_TYPE
, A.PRIORITY
, A.LAST_UPDATE_DATE
, A.EFFDT
, MAX(A.LAST_UPDATE_DATE) OVER(PARTITION BY A.EMPLID) AS MAX_UPDATE_DATE
, ROW_NUMBER() OVER(PARTITION BY A.EMPLID
ORDER BY A.EFFDT DESC
, D.EFFDT DESC) AS RN
FROM PS_DIRECT_DEPOSIT D INNER JOIN PS_DIR_DEP_DISTRIB A ON A.EMPLID = D.EMPLID
AND A.EFFDT = D.EFFDT INNER JOIN PS_EMPLOYEES B ON B.EMPLID = A.EMPLID INNER JOIN PS_GHS_DIR_DEP_VND C ON C.EMPLID = A.EMPLID
INNER JOIN PS_DIR_DEP_DISTRIB E ON E.EMPLID = A.EMPLID AND E.EFFDT = A.EFFDT AND E.PRIORITY = A.PRIORITY
WHERE B.EMPL_STATUS NOT IN ('T','R','D')
AND ((A.DEPOSIT_TYPE = 'P'
AND A.AMOUNT_PCT = 100)
OR A.PRIORITY = 999
OR A.DEPOSIT_TYPE = 'B')
AND D.EFF_STATUS = 'A' )
SELECT CASE WHEN RN = 1 THEN 'NEW ROW' WHEN RN = 2 THEN 'OLD ROW' END AS
'ROW_TYPE' , *
FROM CTE
WHERE RN IN (1, 2)
AND MAX_UPDATE_DATE >= GETDATE() - 8
Вот пример вывода, который я получаю сейчас:
ROW_TYPE EMPLID VENDOR_ID FIRST_NAME LAST_NAME BANK_CD ACCOUNT_NUM ACCOUNT_TYPE PRIORITY LAST_UPDATE_DATE EFFDT MAX_UPDATE_DATE RN
NEW ROW 12345 XYZ123 John Smith 111111122 45678 C 999 03/12/2019 03/12/2019 03/12/2019 1
OLD ROW 12345 XYZ123 John Smith 111111122 45678 C 999 10/25/2017 10/25/2017 10/25/2017 2
NEW ROW 47831 A86464 Samm Bulle 754566654 98865 C 999 03/12/2019 06/08/2018 03/12/2019 1
OLD ROW 47831 A86464 Samm Bulle 754566654 45678 C 999 10/25/2017 06/08/2018 10/25/2017 2
NEW ROW 32456 KG4561 Kilo Renne 875123311 32146 C 300 09/02/2018 09/02/2018 09/02/2018 1
OLD ROW 32456 KG4561 Kilo Renne 971215477 78131 C 310 12/21/2017 12/21/2017 12/21/2017 2
В вышеприведенном примере я НЕ хотел бы выводить первые два набора строк EMPLID (верхние 4 строки), поскольку они имеют одинаковые BANK_CD и ACCOUNT_NUM между старой и новой строкой. Последний набор строк, которые я хотел бы сохранить в своем выводе, как вы видите, BANK_CD и ACCOUNT_NUM различны (хотя могут быть и другие).
Я попытался добавить самообъединение для PS_DIR_DEP_DISTRIB, а затем добавить в предложение WHERE, где AND (A.BANK_CD <> E.BANK_CD OR A.ACCOUNT_NUM <> E.ACCOUNT_NUM) следующим образом:
WITH CTE AS (
SELECT A.EMPLID
--, C.VENDOR_ID
, B.FIRST_NAME
, B.LAST_NAME
, A.BANK_CD
, A.ACCOUNT_NUM
, A.ACCOUNT_TYPE
, A.PRIORITY
, A.LAST_UPDATE_DATE
, A.EFFDT
, MAX(A.LAST_UPDATE_DATE) OVER(PARTITION BY A.EMPLID) AS MAX_UPDATE_DATE
, ROW_NUMBER() OVER(PARTITION BY A.EMPLID
ORDER BY A.EFFDT DESC
, D.EFFDT DESC) AS RN
FROM PS_DIRECT_DEPOSIT D INNER JOIN PS_DIR_DEP_DISTRIB A ON A.EMPLID = D.EMPLID
AND A.EFFDT = D.EFFDT INNER JOIN PS_EMPLOYEES B ON B.EMPLID = A.EMPLID INNER JOIN PS_GHS_DIR_DEP_VND C ON C.EMPLID = A.EMPLID
---ADDING SELF JOIN BELOW---
INNER JOIN PS_DIR_DEP_DISTRIB E ON E.EMPLID = A.EMPLID AND E.EFFDT =
A.EFFDT AND E.PRIORITY = A.PRIORITY
WHERE B.EMPL_STATUS NOT IN ('T','R','D')
AND ((A.DEPOSIT_TYPE = 'P'
AND A.AMOUNT_PCT = 100)
OR A.PRIORITY = 999
OR A.DEPOSIT_TYPE = 'B')
AND D.EFF_STATUS = 'A'
---ADDING NEW WHERE CONDITION BELOW---
AND (E.ACCOUNT_NUM <> A.ACCOUNT_NUM OR E.BANK_CD <> A.BANK_CD ))
SELECT CASE WHEN RN = 1 THEN 'NEW ROW' WHEN RN = 2 THEN 'OLD ROW' END AS 'ROW_TYPE'
, *
FROM CTE
WHERE RN IN (1, 2)
AND MAX_UPDATE_DATE >= GETDATE() - 8
Когда я делаю вышеуказанные изменения, я не получаю никаких данных вообще. Что я делаю не так?
3/20/19 Редактировать:
Следуя предложенному Тареком ответу ниже, мне кажется, что мне не хватает некоторых строк, которые я ожидаю увидеть в конечном выводе. Похоже, что добавленные новые поля BANK_CD_prev
и ACCOUNT_NUM_prev
возвращают значения NULL
в строках, которые я ожидаю, что они будут отображены, поэтому, почему последний запрос не получает их. Как с этим можно справиться?
ROW_TYPE EMPLID FIRST_NAME LAST_NAME BANK_CD ACCOUNT_NUM ACCOUNT_TYPE PRIORITY LAST_UPDATE_DATE EFFDT MAX_UPDATE_DATE RN BANK_CD_prev ACCOUNT_NUM_prev
NEW ROW 56789 Test User 874556411 54765 C 999 2019-02-28 2019-02-28 2019-02-28 1 NULL NULL
OLD ROW 56789 Test User 874556411 98451 C 999 2017-10-09 2017-10-09 2017-10-09 1 874556411 54765
NEW ROW 56789 Sampl Test 756561623 46331 C 999 2018-03-12 2018-03-12 2018-03-12 1 NULL NULL
OLD ROW 56789 Test User 756561623 46331 C 999 2015-05-18 2015-05-18 2015-05-18 1 756561623 46331
Обратите внимание, что в приведенном выше примере выполняется запрос без окончательных условий для (AND BANK_CD <> BANK_CD_prev AND ACCOUNT_NUM <> ACCOUNT_NUM_prev
), чтобы я мог понять, почему мне не хватало некоторых строк. В этом случае вы можете увидеть первые EMPLID
' s две строки, где ACCOUNT_NUM отличается, и поэтому я должен выводить обе строки. 2-я EMPLID
(две последние строки) немного отличается тем, что BANK_CD
и ACCOUNT_NUM
одинаковы для обеих строк, поэтому я не ожидал, что это будет вывод (что не так, так что это правильно), но все равно показывает NULL
как в первом наборе строк.
3/20/19 Edit 2: Вы можете видеть, что в BANK_CD_COUNT
и ACCOUNT_NUM_COUNT
есть какие-то странные цифры, которые, как мне кажется, вызывают проблемы.
ROW_TYPE EMPLID FIRST_NAME LAST_NAME BANK_CD ACCOUNT_NUM ACCOUNT_TYPE PRIORITY LAST_UPDATE_DATE EFFDT MAX_UPDATE_DATE RN BANK_CD_COUNT ACCOUNT_NUM_COUNT
NEW ROW 812682 Test User 031308302 8675309 C 999 2019-03-09 2019-03-09 2019-03-09 1 1101 1
OLD ROW 812682 Test User 231379393 0001236408 C 999 2018-04-11 2018-03-03 2019-03-09 2 476 1
Эта ссылка содержит сценарии создания таблиц и вставки для всех, кто может помочь воспроизвести это.
https://pastebin.com/cZLhMmet