SQL - 检查新行的表?

时间:2009-06-24 14:03:53

标签: sql

我有两张桌子,例如:

Table A                                  Table B
=======                                  =======

Name         | Color                     Name         | Color
----------------------                   ----------------------
Mickey Mouse | red                       Mickey Mouse | red
Donald Duck  | green                     Donald Duck  | blue
Donald Duck  | blue                      Minnie       | red
Goofy        | black
Minnie       | red

表A是我的源表,B是目标表。现在我需要一个查询来查找表A中的所有不同(附加)行,因此可以使用这些行更新表B. 所以我需要一个查询,它从表A中找到以下行:

Name         | Color  
----------------------
Donald Duck  | green  
Goofy        | black

这种查询的好方法是什么?它应尽可能高效(避免过多的连接)。 谢谢你的帮助!

12 个答案:

答案 0 :(得分:9)

我会使用NOT EXISTS结构。

SELECT Name, Color
FROM TableA
WHERE NOT EXISTS (
SELECT 1 FROM TableB
WHERE TableA.Name = TableB.Name 
AND TableA.Color = TableB.Color)

答案 1 :(得分:7)

SELECT a.Name, a.Color
FROM a LEFT OUTER JOIN b ON (a.Name = b.Name AND a.Color = b.Color)
WHERE b.Name IS NULL AND b.Color IS NULL

答案 2 :(得分:4)

Select A.Name, A.Color
From A left join B on A.Name = B.Name and A.Color = B.Color
Where B.Name is null

答案 3 :(得分:2)

在SQL Server 2008中,您可以使用EXCEPT运算符,该运算符像UNION一样使用但返回第一个查询中的所有内容,除非它也位于第二个查询中:

SELECT * FROM TABLEA EXCEPT SELECT * FROM TABLEB

我知道Oracle有一个MINUS运算符可以执行相同的操作。

答案 4 :(得分:2)

您可以使用EXCEPT运算符,它与UNION相反。在Oracle中,相当于MINUS。

SELECT * FROM TABLE_A
EXCEPT
SELECT * FROM TABLE_B

答案 5 :(得分:2)

我通常添加一列“更新TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP”,并使用其值来检查插入新行或修改现有行的时间。

在我开发的应用程序中,我需要解决类似于你的问题,所以我保存了B的MAX(更新)的某个地方,然后通过查询确定了A.updated> B.updated的所有行,并且结果是所有新的+修改过的行。

由于字段默认值为CURRENT_TIMESTAMP且自动更新“ON UPDATE”,因此您无需显式设置其值。

答案 6 :(得分:1)

NOT EXISTS子查询应解析为外连接:

SELECT Name, Color
FROM TableA
WHERE NOT EXISTS (
  SELECT 1
  FROM TableB
  WHERE TableA.Color = TableB.Color
  AND   TableA.Name  = TableB.Name
)

或者您可以直接使用外部联接:

SELECT TableA.Name, TableA.Color
FROM TableA
LEFT OUTER JOIN TableB
  ON  TableA.Name  = TableB.Name
  AND TableA.Color = TableB.Color
WHERE TableB.Name IS NULL

他们应该具有同等的表现;这是一个你觉得更直观的问题。

答案 7 :(得分:1)

已经有很多正确的答案,但我想提出一个哲学观点:

此数据库架构在单个架构内的生产环境中是否真的可行?

让两个包含数据的表,然后编写一个查询来比较一个是否真的有意义吗?我认为只有一个表是有意义的,也许放入一个日期标识符来查找在某一点之后添加的记录。

我能想到的唯一情况就是你有两个独立的数据库,你想要“同步”它们,或者当你想要找到两者之间的差异时,比如说备份和生产。

答案 8 :(得分:1)

在Oracle中你可能会使用:

MERGE INTO b USING
  (SELECT name, color 
     FROM a) src 
 ON (src.name = b.name AND color = src.color)
 WHEN NOT MATCHED THEN 
    INSERT (name, color)
    VALUES (src.name, src.color);

如果你的表有一个主键(你真的有没有一个表吗?),比如NAME,你想根据表B中记录的存在进行INSERT或UPDATE,你可以使用:

MERGE INTO b USING 
  (SELECT name, color 
     FROM a) src 
  ON (src.name = b.name) 
  WHEN NOT MATCHED THEN 
    INSERT (name, color)
    VALUES (src.name, src.color) 
  WHEN MATCHED THEN 
    UPDATE 
    SET color = src.color; 

我认为SQL Server也有MERGE语句或类似语句。

答案 9 :(得分:0)

SELECT TableA.Name, TableA.Color FROM TableA WHERE TableA.Name + TableA.Color NOT IN (SELECT TableB.Name + TableB.Color FROM TableB)

答案 10 :(得分:0)

INSERT INTO B 
SELECT a.Name, a.Color
FROM A a
LEFT JOIN B b ON a.Name = b.Name AND a.Color = b.Color
WHERE b.Color IS NULL AND b.Name IS NULL

答案 11 :(得分:0)

public static TableId getTemporaryTable(String query) throws InterruptedException{
    QueryJobConfiguration queryConfig = 
                QueryJobConfiguration.newBuilder(query)
                    .setUseLegacySql(false)
                    .build();
    Job queryJob = bigquery.create(JobInfo.newBuilder(queryConfig).build());
    queryJob = queryJob.waitFor(); // Wait for the query to complete.
    return ((QueryJobConfiguration) queryJob.getConfiguration()).getDestinationTable();
}

可以在 db fiddle

找到工作腼腆