比较两个连接表中的行,并以交替方式提供两个表的结果

时间:2018-03-08 04:53:21

标签: sql sql-server tsql join

Table X

First Name    Last Name    Job
----------    ---------    ---
CHIN          JACK         A
GREEN         JAMES        B

Table Y

First Name    Last Name    Job
----------    ---------    ---
CHIN          JACK         D
GREEN         JAMES        B


  RESULT
------
First Name          Last Name           Job
----------          ---------           ---
CHIN                JACK                >> A <<   --(first row from Table X)
CHIN                JACK                >> D <<   --(first row from Table Y)
>> CHIN <<          >> JACK <<          >> A <<   --(first row from Table X)
>> GREEN <<         >> JAMES <<         >> B <<   --(second row from Table Y)
>> GREEN <<         >> JAMES <<         >> B <<   --(second row from Table X)
>> CHIN <<          >> JACK <<          >> D <<   --(first row from Table Y)
GREEN               JAMES               B         --(second row from Table X) 
GREEN               JAMES               B         --(second row from Table Y)

我试图逐列比较两个表中的行。如果两个表之间的列值不匹配,请通过附加'&gt;&gt;突出显示它。 &LT;&LT;”对于结果表中表TableX和TableY中的不匹配字段。结果表交替显示TableX和TableY中的行。请查看结果表以更好地了解我的预期结果。

结果集的最后两个表是可选的。拥有它还是不拥有它我没事。

这个查询是我最初想到的,但它没有交替给出两个表中的行,它只考虑TableX中的列值 是否有可能编写查询来实现结果表。请指教。

SELECT
CASE
  WHEN x.firstname = y.firstname THEN x.firstname
  ELSE '>> '+x.firstname+' <<'
END FirstName,
CASE 
  WHEN x.lastname = y.lastname THEN x.lastname
  ELSE '>> '+x.lastname+' <<'
END LastName,
CASE 
  WHEN x.job = y.job THEN x.job
  ELSE '>> '+x.job+' <<'
END Job
FROM
TableX x
JOIN
TableY y
ON x.firstname <> y.firstname
OR x.lastname <> y.lastname
OR x.job <> y.job

改进 我发现了一个非常类似于我预期结果的查询。我通过添加一个新的列'Company'来实现它,其值在TableX和TableY中始终相同。所以现在表格看起来像

表X

Company    First Name    Last Name    Job
-------    ----------    ---------    ---
C          CHIN          JACK         A
C          GREEN         JAMES        B

表Y

Company    First Name    Last Name    Job
-------    ----------    ---------    ---
T          CHIN          JACK         D
T          GREEN         JAMES        B

这是我的新查询

    SELECT
    *
FROM 
(
SELECT      ROW_NUMBER() OVER (ORDER BY x.Company) as RowNumber,
            1 AS 'RowOrder',
            x.TableName,
            CASE
                WHEN x.firstname = y.firstname THEN x.firstname
                ELSE '>> '+x.firstname+' <<'
            END FirstName,
            CASE
                WHEN x.LastName = y.LastName THEN x.LastName
                ELSE '>> '+x.LastName+' <<'
            END LastName,
            CASE
                WHEN x.Job = y.Job THEN x.Job
                ELSE '>> '+x.Job+' <<'
            END Job
    FROM
            #tableX x
        JOIN #tableY y
        ON x.FirstName <> y.FirstName
        OR x.LastName <> y.LastName
        OR x.Job <> y.Job

UNION ALL

SELECT 
            ROW_NUMBER() OVER (ORDER BY y.Company) as RowNumber,
            2 AS 'RowOrder',
            y.TableName,
            CASE
                WHEN x.firstname = y.firstname THEN y.firstname
                ELSE '>> '+y.firstname+' <<'
            END FirstName,
            CASE
                WHEN x.LastName = y.LastName THEN y.LastName
                ELSE '>> '+y.LastName+' <<'
            END LastName,
            CASE
                WHEN x.Job = y.Job THEN y.Job
                ELSE '>> '+y.Job+' <<'
            END Job
    FROM
            #tableX x
        JOIN #tableY y
        ON x.FirstName <> y.FirstName
        OR x.LastName <> y.LastName
        OR x.Job <> y.Job

) rt
ORDER BY rt.RowNumber, rt.RowOrder

现在的问题是大括号内第二个select语句的连接会扰乱显示行的顺序。这导致最终结果中的行排序错误。请在下面找到最终结果。您还可以在大括号内找到各个select语句。图中的最后一个表给出了乱序的行,这些行会弄乱最终的结果。

Final result, result from first select statement, result from second select statement

1 个答案:

答案 0 :(得分:0)

我认为你要比较两个表之间的所有行对。只是意识到这会很快变大和变慢。

with X as (
    select *, row_number() over (order by "First Name", "Last Name", "Job") as rnX
    from TableX
), Y as (
    select *, row_number() over (order by "First Name", "Last Name", "Job") as rnY
    from TableY
), horizontal as (
    select
        rnX, rnY,
        case when x."First Name" = y."First Name" then x."First Name"
            else '>> ' + x."First Name" + ' <<' end as FirstNameX,
        case when x."First Name" = y."First Name" then y."First Name"
            else '>> ' + y."First Name" + ' <<' end as FirstNameY,
        case when x."Last Name" = y."Last Name" then x."Last Name"
            else '>> ' + x."Last Name" + ' <<' end as LastNameX,
        case when x."Last Name" = y."Last Name" then y."Last Name"
            else '>> ' + y."Last Name" + ' <<' end as LastNameY,
        case when x."Job" = y."Job" then x."Job"
            else '>> ' + x."Job" + ' <<' end as JobX,
        case when x."Job" = y."Job" then y."Job"
            else '>> ' + y."Job" + ' <<' end as JobY
    from X as x cross join Y as y
), interleave as (
    select
        rnX, rnY, n,
        case when n = 1 then 'X' else 'Y' end as src,
        case when n = 1 then rnX else rnY end as rn,
        case when n = 1 then FirstNameX else FirstNameY end as "First Name",
        case when n = 1 then LastNameX else LastNameY end as "Last Name",
        case when n = 1 then JobX else JobY end as "Job"
    from horizontal cross apply (select n from (values (1), (2)) d(n)) c
)
select src, rn, "First Name", "Last Name", "Job" from interleave
order by rnX, rnY, n;

http://rextester.com/JRQ91122