mysql 是否可以在此查询中将不存在替换为连接?

jv2fixgn  于 2022-10-31  发布在  Mysql
关注(0)|答案(2)|浏览(124)

我有这样的疑问

SELECT * 
FROM table1 as t1
WHERE (t1.phone != "" OR t1.sms_phone != "")
  and t1.docType in (1,2,3)
  and not exists (select id from table2 where product_id=1 and doc_id=t1.id);

而我想用JOIN来替换带有“不存在”的部分,所以我尝试了这种方法:

SELECT * 
FROM table1 as t1
LEFT OUTER JOIN table2 
  ON table2.doc_id = t1.id 
  AND table2.product_id = 1
  and table2.id IS NULL
WHERE (t1.phone != "" OR t1.sms_phone != "")
  and t1.docType in (1,2,3);

但第二个查询返回的记录要多得多。

kmbjn2e3

kmbjn2e31#

SELECT t1.*
FROM table1 AS t1 
LEFT JOIN table2 AS t2 ON t2.product_id=1 AND t2.doc_id=t1.id
WHERE (t1.phone != "" OR t1.sms_phone != "") 
  AND t1.docType in (1,2,3) 
  AND t2.doc_id IS NULL

它是如何工作的(正式地,从用户的Angular 来看)?
1.我们取表1并选择与(t1.phone != "" OR t1.sms_phone != "") AND t1.docType in (1,2,3)匹配的行,因为这些条件只处理表1。不匹配的行将被逐出。
1.我们取表2并选择与t2.product_id=1匹配的行,因为此条件只处理表2。不匹配的行将被逐出。
1.现在,我们使用t2.doc_id=t1.id组合这些行。t2中不匹配的行将被逐出。
1.现在,根据t2.doc_id IS NULL,我们仅选择t1中没有t2中的配对行的那些行。
根据形式执行逻辑,#1必须在#3和#4之间执行,但这不会影响结果(无论如何,这些行都会被弹出),所以我把它放在最前面。

mznpcxlj

mznpcxlj2#

我认为在第二个查询中有一个错误,并且“FROM table1 as t1office_id”部分不属于这个查询。

SELECT * 
  FROM table1 as t1 
  LEFT OUTER JOIN table2 
    ON table2.doc_id = t1.id 
   AND table2.product_id = 1 
   and table2.id IS NULL 
 WHERE (t1.phone != "" OR t1.sms_phone != "") and t1.docType in (1,2,3);

当使用外连接时,过滤产生的结果会因i的位置而有所不同。
基本上,您的查询是“将t1与table2中除.....之外的所有行进行外部连接"。这将使您获得等于或多于t1行数的行数。
您需要考虑的是连接所有行并在AFTERWARDS后过滤它们。要实现这一点,您必须将过滤子句移到查询的WHERE部分。请尝试以下操作:

SELECT * 
  FROM table1 as t1 
  LEFT OUTER JOIN table2 
    ON table2.doc_id = t1.id 
 WHERE (t1.phone != "" OR t1.sms_phone != "") 
   and t1.docType in (1,2,3)
   AND table2.product_id = 1 
   and table2.id IS NULL;

相关问题