сравнивать столбцы только когда NOT NULL - PullRequest
5 голосов
/ 26 марта 2019

Это должно быть легко, но я просто что-то упустил. У меня есть следующее:

IF OBJECT_ID('LAST_NM') IS NOT NULL
    DROP TABLE LAST_NM

CREATE TABLE LAST_NM (
    ID int NOT NULL IDENTITY(1,1),
    LAST_NM_ORIGINAL varchar(255) NOT NULL,
    LAST_NM_1 varchar(255)NULL,
    LAST_NM_2 varchar(255)NULL,
    LAST_NM_3 varchar(255)NULL,
    LAST_NM_4 varchar(255)NULL,
    PRIMARY KEY (ID)
);

INSERT INTO LAST_NM
(LAST_NM_ORIGINAL, LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)
VALUES
('SMITH', 'HARRIS', NULL, 'HARRIS', NULL),
('JONES', 'FUTURE', 'FUTURE', 'FUTURE', 'FUTURE'),
('SMITH', 'ALPHA', 'ALPHA', 'ALPHA', NULL),
('SMITH', 'BETA', 'BETA', 'GEORGE', NULL),
('SMITH', 'SMITH', NULL, 'SMITH', NULL),
('DOPE', NULL, NULL, NULL, 'CURLS')

Что я хочу сделать, это SELECT из этой таблицы, где:

  • the last_nm_ # IS NOT NULL
  • NOT NULL last_nm_ # имеют одинаковое значение
  • эти last_nm_ # не совпадают с LAST_NM_ORIGINAL

Я попытался поиграть с CASE и SWITCH, и у меня получилась грязная версия, если я жестко запрограммировал все выражения и объединил их так:


SELECT * FROM (
    SELECT ID, LAST_NM_ORIGINAL, LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4
    FROM LAST_NM
    WHERE       LAST_NM_1 IS NOT NULL
            AND LAST_NM_2 IS NOT NULL
            AND LAST_NM_3 IS NOT NULL
            AND LAST_NM_4 IS NOT NULL
            AND LAST_NM_1 = LAST_NM_2
            AND LAST_NM_1 = LAST_NM_3
            AND LAST_NM_3 = LAST_NM_4
            AND LAST_NM_1 <> LAST_NM_ORIGINAL
    UNION
    SELECT ID, LAST_NM_ORIGINAL, LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4
    FROM LAST_NM
    WHERE       LAST_NM_1 IS NOT NULL
            AND LAST_NM_2 IS NOT NULL
            AND LAST_NM_3 IS NOT NULL
            AND LAST_NM_4 IS NULL
            AND LAST_NM_1 = LAST_NM_2
            AND LAST_NM_1 = LAST_NM_3
            AND LAST_NM_1 <> LAST_NM_ORIGINAL
    /*
    WRITE OUT EACH POSSIBLE WAY AND UNION ALL OF THEM
    .
    .
    .
    */
    UNION
    SELECT ID, LAST_NM_ORIGINAL, LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4
    FROM LAST_NM
    WHERE       LAST_NM_1 IS NULL
            AND LAST_NM_2 IS NULL
            AND LAST_NM_3 IS NULL
            AND LAST_NM_4 IS NOT NULL
            AND LAST_NM_4 <> LAST_NM_ORIGINAL
    ) AS RESULT_SET

Подводя итог, я хочу выделить строки, если LAST_NM_# не равен NULL и совпадает со всеми остальными NOT NULL LAST_NM_# и отличается от LAST_NM_ORIGINAL

Так что в моем примере я должен получить строки 1, 2, 3 и 6. Но не строки 4 («новые» имена не согласны) или строку 5 (новые имена совпадают со старыми один).

Должен быть лучший способ, чем просто записать каждый из них и ОБЪЕДИНИТЬ их .. верно?

Ответы [ 6 ]

2 голосов
/ 26 марта 2019

Здесь используется UNPIVOT

;WITH NAMES
AS (
    SELECT DISTINCT ID
        ,LAST_NM_ORIGINAL
        ,LAST_NM_NEW
    FROM (
        SELECT ID
            ,LAST_NM_ORIGINAL
            ,LAST_NM_1
            ,LAST_NM_2
            ,LAST_NM_3
            ,LAST_NM_4
        FROM LAST_NM
        ) AS X
    UNPIVOT(LAST_NM_NEW FOR LAST_NM_NEWS IN (
                LAST_NM_1
                ,LAST_NM_2
                ,LAST_NM_3
                ,LAST_NM_4
                )) AS Y
    )
SELECT ID
    ,LAST_NM_ORIGINAL
    ,LAST_NM_NEW
FROM NAMES
WHERE ID IN (
        SELECT ID
        FROM NAMES
        GROUP BY ID
        HAVING COUNT(ID) = 1
        )
    AND LAST_NM_ORIGINAL <> LAST_NM_NEW
1 голос
/ 27 марта 2019

Вот еще один способ сделать это

SELECT * FROM
#LAST_NM 
WHERE
COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4) = COALESCE(LAST_NM_2, LAST_NM_3, LAST_NM_4,LAST_NM_1)
AND COALESCE(LAST_NM_2, LAST_NM_3, LAST_NM_4,LAST_NM_1) = COALESCE(LAST_NM_3, LAST_NM_4,LAST_NM_1,LAST_NM_2)
AND COALESCE(LAST_NM_3, LAST_NM_4,LAST_NM_1,LAST_NM_2) = COALESCE(LAST_NM_4,LAST_NM_1,LAST_NM_2,LAST_NM_3)
AND (LAST_NM_ORIGINAL <> COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4))
1 голос
/ 26 марта 2019

Ваш исходный запрос имеет некоторые лишние предикаты.Любое собрание строк LAST_NM_1 = LAST_NM_2 гарантированно будет иметь, например, LAST_NM_1 NOT NULL и LAST_NM_2 NOT NULL.

Но это можно сделать довольно сжатым, используя VALUES, чтобы получить 4 столбца в табличной форме, как показано ниже.

SELECT *
FROM   LAST_NM
WHERE  EXISTS (SELECT *
               FROM   (VALUES(LAST_NM_1),
                             (LAST_NM_2),
                             (LAST_NM_3),
                             (LAST_NM_4)) V(LAST_NM_N)
               HAVING MAX(LAST_NM_N) = MIN(LAST_NM_N) /*exactly one NOT NULL value among the 4 columns*/
                      AND MAX(LAST_NM_N) <> LAST_NM_ORIGINAL) 
1 голос
/ 26 марта 2019

Этот вопрос сразу кричит мне НЕУДАЧНО .

Вы можете увидеть ссылку или просто Google для синтаксиса и примеров, а затем использовать его, чтобы получить производную таблицу, которая выглядит следующим образом:

ID NM_Orig   NM_Number  NM_Value
1  Smith     1          Harris
1  Smith     2          NULL
1  Smith     3          Harris
1  Smith     4          NULL
2  Jones     1          Future
etc...

Из этой производной таблицы вы запроситеполучить идентификаторы WHERE NM_Value is NOT NULL AND NM_Value <> NM_Orig AND WHERE NOT EXISTS коррелированная строка с ненулевым значением NM_Value, отличным от коррелированной NM_Value.

1 голос
/ 26 марта 2019

Вот еще один способ сделать это.

SELECT
    *
FROM
    LAST_NM
WHERE
    (LAST_NM_1 IS NULL OR LAST_NM_1 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_2 IS NULL OR LAST_NM_2 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_3 IS NULL OR LAST_NM_3 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_4 IS NULL OR LAST_NM_4 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_1 IS NULL OR LAST_NM_1 <> LAST_NM_ORIGINAL) AND
    (LAST_NM_2 IS NULL OR LAST_NM_2 <> LAST_NM_ORIGINAL) AND
    (LAST_NM_3 IS NULL OR LAST_NM_3 <> LAST_NM_ORIGINAL) AND
    (LAST_NM_4 IS NULL OR LAST_NM_4 <> LAST_NM_ORIGINAL)

Редактировать.Можно сократить до запроса ниже, так как вы хотите, чтобы хотя бы один из LAST_NM_ # не был нулевым:

SELECT
    *
FROM
    LAST_NM
WHERE
    (LAST_NM_1 IS NULL OR LAST_NM_1 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_2 IS NULL OR LAST_NM_2 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_3 IS NULL OR LAST_NM_3 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_4 IS NULL OR LAST_NM_4 = COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4)) AND
    (LAST_NM_ORIGINAL <> COALESCE(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4))
1 голос
/ 26 марта 2019

Вот один из способов сделать это.

select ID
    , LAST_NM_ORIGINAL
    , LAST_NM_1
    , LAST_NM_2
    , LAST_NM_3
    , LAST_NM_4
from LAST_NM
where replace(isnull(LAST_NM_1, '') + isnull(LAST_NM_2, '') + isnull(LAST_NM_3, '') + isnull(LAST_NM_4, ''), LAST_NM_ORIGINAL, '') > ''
    AND replace(isnull(LAST_NM_1, '') + isnull(LAST_NM_2, '') + isnull(LAST_NM_3, '') + isnull(LAST_NM_4, ''), coalesce(LAST_NM_1, LAST_NM_2, LAST_NM_3, LAST_NM_4), '') = ''
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...