简体   繁体   中英

Show the difference between two columns from two different tables (comparison table)

I have two tables with the same structure and almost identical content. The main difference is that one value column may differ from the 'equivalent' one in the second table. On top of that, one record may appear in one table, but not in the other.

My tables:

Table1 (idA, valueA, valueB, valueC (nullable), valueX)
Table2 (idB, valueA, valueB, valueC (nullable), valueY)

Desired result:

Table3 (valueA, valueB, valueC, valueX, valueY)

Preconditions:

  • 'id' is a primary key and can differ in the two tables
  • 'valueC' is the only column that can have a null value. However, the value will be the same in both tables.
  • If a record appears in Table1 but not in Table2, 'valueY' shall be null
  • If a record appears in Table2 but not in Table1, 'valueX' shall be null

Example:

Table1
1 | 1001 | 2001 | 3001 | 100.0
2 | 1002 | 2002 | 3002 | 95.0
3 | 1003 | 2003 | (null) | 113.0
4 | 1004 | 2004 | 3004 | 75.0

Table2
23 | 1001 | 2001 | 3001 | 100.0
24 | 1002 | 2002 | 3002 | 94.0
25 | 1003 | 2003 | (null) | 116.0
26 | 1005 | 2005 | 3005 | 32.0

The desired result should be:

Table3
1001 | 2001 | 3001 | 100.0 | 100.0
1002 | 2002 | 3002 | 95.0 | 94.0
1003 | 2003 | (null) | 113.0 | 116.0
1004 | 2004 | 3004 | 75.0 | (null)
1005 | 2005 | 3005 | (null) | 32.0

I think I have come up with a solution but it is extremely slow and I am not sure if this really is the easiest way to do this.

SELECT valueA, valueB, valueC, valueX, valueY
FROM (
    (SELECT t1.valueA, t1.valueB, t1.valueC, t1.valueX, t2.valueY
    FROM Table1 t1
    LEFT JOIN Table2 t2
        ON t1.valueA = t2.valueA 
        AND t1.valueB = t2.valueB 
    WHERE t1.valueC = t2.valueC OR t1.valueC IS NULL OR t2.valueC IS NULL)
    UNION
    (SELECT t2.valueA, t2.valueB, t2.valueC, t1.valueX, t2.valueY
    FROM Table2 t2
    LEFT JOIN Table1 t1
        ON t1.valueA = t2.valueA 
        AND t1.valueB = t2.valueB 
    WHERE t1.valueC = t2.valueC OR t1.valueC IS NULL OR t2.valueC IS NULL)
    );

I hope someone can come up with a more 'elegant' solution. As a side note, I am using an Oracle DB. Thanks in advance for your time and help!

将表c创建为(从表中选择*从表B中减去*从表B中选择)并(从表b中选择*从表A中减去*

This query gives desired output. I don't know if it's more elegant, but is shorter for sure ;-)

select valueA, valueB, nvl(table1.valueC, table2.valueC) valueC, valueX, valueY 
  from table1
    full join table2 using (valueA, valueB)
  order by valueA

BTW your query gave only 4 rows, without 1004 | 2004 | 3004 | 75.0 | (null) 1004 | 2004 | 3004 | 75.0 | (null) 1004 | 2004 | 3004 | 75.0 | (null) , probably your where should be:

where t1.valueC = t2.valueC OR t1.valueC IS NULL or t2.valueC IS NULL

instead of

WHERE t1.valueC = t2.valueC OR (t1.valueC IS NULL AND t1.valueC IS NULL)

Reworked query

select a, b, nvl(t1c, t2c) c, x, y
  from (
    select nvl(t1.valueA, t2.valueA) a, nvl(t1.valueB, t2.valueB) b, 
        t1.valueC t1c, t2.valueC t2c, valueX x, valueY y
      from table1 t1 
        full join table2 t2 on (t1.valueA = t2.valueA and t1.valueB = t2.valueB
          and ( t1.valueC = t2.valueC or (t1.valueC is null and t2.valueC is null) ) )
        )
  order by a, b, c

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM