Python SQL如何查找其他表中的不匹配项?

时间:2018-12-30 10:42:06

标签: python sql mariadb

我正在寻找解决方案,以便可以检查其他表中的不匹配项。

基本上我有3张桌子(见下文)。在这里,我要查看表1,并确定第一行在“名称”或“位置”中均不匹配。如果两者都被识别,则应移至下一行并进行检查。

我试图用SQL来完成此任务并遍历它们,但是由于我只希望第一行不匹配,所以我没有找到一个平滑的解决方案(或者正因为如此,我很新手-ish)。

我很确定这可以通过SQL来完成。

表1

Id   Name  Location
1    John  Canada
2    James Brazil
3    Jim   Hungary

表2-公认的名称

Id   Name
1    John
2    James

表3-可以识别的位置

Id   Location
1    Brazil
2    Hungary

所以我想从表1中进行选择,其中“名称”在表2中找不到匹配项,或者“位置”在表3中找不到匹配项。

在上面的示例中,结果应为Id = 1,因为“位置”不在表3中。

谢谢。

1 个答案:

答案 0 :(得分:2)

您可以使用not exists来选择是否某些子查询未选择行:

select
  *
from
  Table1 t1
where
  not exists (
    select * from Table2 t2 where t2.`Name` = t1.`Name`
  ) and
  not exists (
    select * from Table3 t3 where t3.`Location` = t1.`Location`
  )
order by
  t1.Id
limit 1

这不是一个非常复杂的查询,但是仍然有一些事情在进行,因此这里还是相同的,但是带有注释以解释各个部分:

select
  /* I select all columns, *, for the example, but in real life scenarios 
     it's always better to explicitly specify which columns you need. */
  *
from
  /* Optionally, you can specify a short or different alias for a table (t1)
     this can be helpful to make your query more readable by allowing you to explicitly
     specify where a column is coming from, without cluttering the query with long names. */
  Table1 t1
where
  /* exists takes a sub-query, which is executed for each row of the main query.
     The expression returns true if the subquery returns a row. 
     With not (not exists), the expression is inversed: true becomes false. */
  not exists (
    /* In MariaDB, backticks can be used to escape identifiers that also are 
       reserved words. You are allowed to use them for any identifier, but
      for reserved word identifiers, they are often necessary. */
    select * from Table2 t2 where t2.`Name` = t1.`Name`
  )
  /* Combine the two subqueries. We only want rows don't have a matching row 
     in sub-query one, and neither in sub-query two. */
  and
  not exists (
    select * from Table3 t3 where t3.`Location` = t1.`Location`
  )
/* Specify _some_ ordering by which you can distinguish 'first' from 'second'. */
order by
  t1.Id
/* Return only 1 row (the first according to the order clause) */
limit 1