仅在NOT NULL时比较列

sni*_*erd 5 sql-server

这应该很容易,但是我只是缺少一些东西。我有以下几点:

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')
Run Code Online (Sandbox Code Playgroud)

我想做的是SELECT从此表中:

  • last_nm_# IS NOT NULL
  • NOT NULL last_nm_#都具有相同的值
  • 这些last_nm_#与 LAST_NM_ORIGINAL

I've tried playing with CASE and SWITCH and I got a messy version working if I hard code the heck out of statements and union them like this:


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
Run Code Online (Sandbox Code Playgroud)

To summarize, I want to select out the rows if the LAST_NM_# is not NULL and is the same as all the other NOT NULL LAST_NM_# and is different than the LAST_NM_ORIGINAL

So in my example, I should get back rows 1, 2, 3, and 6. But not rows 4 (the 'new' names don't agree) or row 5 (the new names are the same as the old one).

There has to be a better way than just writing each of those out and UNIONING them.. right?

小智 2

这里使用的是 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
Run Code Online (Sandbox Code Playgroud)