代码之家  ›  专栏  ›  技术社区  ›  EmmyS

如何比较两个相同表中的行并返回丢失行的结果集?

  •  4
  • EmmyS  · 技术社区  · 14 年前

    我已经看过所有相关的问题,但没有一个能完全满足我的需要。我有两个结构相同的表(ID、Vouchernbr、BalanceInit)——一个来自我们当前的生产系统(TableA),另一个来自客户的遗留系统(TableB)。表A有记录A、B、C、D、E(例如),表B有A、B、C、D、E、F、G。表B将始终具有表A中存在的所有值,但也有多余的行。我需要返回一个结果集,该结果集包含表B中不存在于表A中的所有行(F和G,使用示例)。我如何才能这样做?

    编辑:

    表A

    ID | VoucherNbr         | BalanceInit
    =============================================
    1  | 1111111111111111   | 25.00
    2  | 2222222222222222   | 50.00
    3  | 3333333333333333   | 10.00
    

    表B

    ID | VoucherNbr         | BalanceInit
    =============================================
    15 | 1111111111111111   | 25.00
    17 | 1212121212121212   | 15.00
    22 | 2222222222222222   | 50.00
    34 | 3333333333333333   | 25.00
    41 | 3232323232323232   | 75.00
    

    我需要返回的是只包含表A中不存在的行的结果集,其中Vouchernbr字段中不存在的值,而不是ID字段。

    ID | VoucherNbr         | BalanceInit
    =============================================
    17 | 1212121212121212   | 15.00
    41 | 3232323232323232   | 75.00
    
    3 回复  |  直到 14 年前
        1
  •  9
  •   Larry Lustig    14 年前

    有些数据库直接使用减法或减法操作提供此功能。MySQL似乎没有这样的操作。

    我可能会这样做:

    SELECT  B.id, B.voucherNbr, B.balanceInit FROM tableB B
       WHERE NOT EXISTS 
         (SELECT * FROM tableA A 
          WHERE A.voucherNbr = B.voucherNbr AND A.balanceInit = B.balanceInit)
    

    但是,这里有几个其他的MySQL解决方案(我在谷歌上搜索过),您可以测试速度:

    SELECT  id, voucherNbr, balanceInit FROM tableB 
       WHERE (voucherNbr, balanceInit) NOT IN 
          (SELECT voucherNbr, balanceInit FROM tableA);
    
    SELECT  id, voucherNbr, balanceInit
       FROM tableB LEFT JOIN tableA USING (voucherNbr, balanceInit)
          WHERE tableA.voucherNbr IS NULL
    

    老实说,如果执行时间相似或更好,我更喜欢第一个谷歌解决方案。

    注意:我已经从原始答案修改了这些内容,以反映您在注释中陈述的事实,以及在两个表中ID不同的另一个答案。

        2
  •  1
  •   Jagmag    14 年前

    注:假设 id 是两个表的pk。

    SELECT B.* FROM TableB B 
    LEFT OUTER JOIN TableA A
    ON B.id = A.id
    WHERE A.id IS NULL
    

    编辑:基于来自op的进一步注释,因为对于两个表中的同一行,ID是不同的,假设匹配条件是基于比较两个列的值

    SELECT B.* FROM TableB B 
    LEFT OUTER JOIN TableA A
    ON B.VoucherNbr = A.VoucherNbr
    AND B.BalanceInit = A.BalanceInit
    WHERE A.VoucherNbr IS NULL 
    

    edit2:如果只有凭证号本身足够,则BalanceInit也可以丢弃。

    SELECT B.* FROM TableB B 
    LEFT OUTER JOIN TableA A
    ON B.VoucherNbr = A.VoucherNbr
    WHERE A.VoucherNbr IS NULL 
    
        3
  •  0
  •   Sammy    14 年前

    你可以使用 横断 静物

    SELECT * FROM tableA 
    INTERSECT 
    SELECT * FROM tableB 
    

    -except返回左查询中在右查询中未找到的任何不同值。

    -intersect返回由intersect操作数左右两侧的查询返回的任何不同值。

    http://msdn.microsoft.com/en-us/library/ms188055.aspx