MySQL中的Intersect替代方案

MySQL中的Intersect替代方案,mysql,intersect,Mysql,Intersect,我需要在MySQL中实现以下查询 (select * from emovis_reporting where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') ) intersect ( select * from emovis_reporting where (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') ) 我知道intersect不在MySQL中。所以我需要另一种方法。 请告诉我。您的查询将始终

我需要在MySQL中实现以下查询

(select * from emovis_reporting where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') ) 
intersect
( select * from emovis_reporting where (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') )
我知道intersect不在MySQL中。所以我需要另一种方法。
请告诉我。

您的查询将始终返回一个空记录集,因为cut\u name='0全プロセス' 然后切下你的名字恐慌' 将永远不会评估为真

一般来说,MySQL中的INTERSECT应该如下模拟:

SELECT  *
FROM    mytable m
WHERE   EXISTS
        (
        SELECT  NULL
        FROM    othertable o
        WHERE   (o.col1 = m.col1 OR (m.col1 IS NULL AND o.col1 IS NULL))
                AND (o.col2 = m.col2 OR (m.col2 IS NULL AND o.col2 IS NULL))
                AND (o.col3 = m.col3 OR (m.col3 IS NULL AND o.col3 IS NULL))
        )
如果两个表的列都标记为NOTNULL,则可以省略IS NULL部分,并在以下情况下使用更高效的方法重写查询:


AFAIR,MySQL实现了INTERSECT TO。

Microsoft SQL Server返回INTERSECT操作数左右两侧的查询返回的任何不同值。这与标准内部联接或WHERE EXISTS查询不同

SQL Server

MySQL

这个问题涉及到id列,因此不会返回重复的值,但是为了完整起见,这里有一个使用内部连接和DISTINCT的MySQL替代方案:

另一个例子是使用WHERE。。。以不同的方式:


为了完整起见,这里有另一种模拟INTERSECT的方法。请注意,选择中的。。。其他答案中建议的形式通常更有效

通常,对于名为mytable的表以及名为id的主键:

请注意,如果在这个查询中使用SELECT*,您将得到两倍于mytable中定义的列,这是因为内部联接生成


这里的内部联接生成表中的每一行对。这意味着以每种可能的顺序生成每一行的组合。WHERE子句然后过滤该对的a侧,然后过滤b侧。结果是只返回满足这两个条件的行,就像两个查询的交集一样。

有一种更有效的生成交集的方法,使用UNION ALL和GROUP by。根据我在大型数据集上的测试,性能提高了两倍

例如:

SELECT t1.value from (
  (SELECT DISTINCT value FROM table_a)
  UNION ALL 
  (SELECT DISTINCT value FROM table_b)
) AS t1 GROUP BY value HAVING count(*) >= 2;

它更有效,因为使用内部连接解决方案,MySQL将查找第一个查询的结果,然后在第二个查询中查找每一行的结果。使用UNION ALL-GROUP BY解决方案,它将查询第一次查询的结果、第二次查询的结果,然后将所有结果一次分组在一起

将您的问题分为两种陈述:首先,如果需要,请选择all

SELECT
  campo1,
  campo2,
  campo3,
  campo4
FROM tabela1
WHERE CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
NOT IN
(SELECT CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
FROM tabela2);
(id=3 and cut_name= '全プロセス' and cut_name='恐慌')
这是真的。其次,如果需要,您希望选择all

(id=3) and ( cut_name='全プロセス' or cut_name='恐慌')
这是真的。因此,我们将通过或加入,因为如果其中任何一个为真,我们希望选择all

select * from emovis_reporting
    where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') OR
        ( (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') )

我刚刚在MySQL 5.7中检查了它,我真的很惊讶没有人给出一个简单的答案:自然连接

当表或选择结果具有相同的列时,可以使用自然联接作为查找交点的方法:

例如:

表1:

身份证,姓名,职务证

“1”、“约翰”、“1”

“2”,“杰克”,“3”

“3”,“亚当”,“2”

“4”、“比尔”、“6”

表2:

身份证,姓名,职务证

“1”、“约翰”、“1”

“2”,“杰克”,“3”

“3”,“亚当”,“2”

“4”、“比尔”、“5”

“5”、“最多”、“6”

以下是查询:

SELECT * FROM table1 NATURAL JOIN table2;
查询结果: 身份证,姓名,职务证

“1”、“约翰”、“1”

“2”,“杰克”,“3”


“3”、“Adam”、“2”

cut\u name对于任何给定行都不能有两个不同的值,因此第一个select不会返回任何内容。不,内部联接产生笛卡尔积。这意味着第一个表中的每一行的排列,第二个表中的每一行都会生成。但是,如果使用适当的WHERE子句,这可以用于应用与INTERSECT相同的逻辑,请参见我的答案。但是,您不能将内部联接与USING子句一起使用,它实际上与INTERSECT相同吗?UNION ALL不会删除重复项,我认为在这种情况下使用并集会更好地获得准确的交点。@code2be:这就是问题所在,您不想删除重复项,不想计算结果的数量,也不想满足count*>=2的子句。如果不使用UNION ALL,这将不起作用。mysql本身是否有任何查询优化,这将为这些可比较的查询选择更好的执行路径?@Barmar:不会,因为我们在每个查询中都使用DISTINCT子句subqueries@Barmar哈,我的错!为什么要在值周围加括号?不管这是否正确,都应该在代码块中格式化代码,并描述如何/为什么这样解决问题。
SELECT t1.value from (
  (SELECT DISTINCT value FROM table_a)
  UNION ALL 
  (SELECT DISTINCT value FROM table_b)
) AS t1 GROUP BY value HAVING count(*) >= 2;
SELECT
  campo1,
  campo2,
  campo3,
  campo4
FROM tabela1
WHERE CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
NOT IN
(SELECT CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
FROM tabela2);
(id=3 and cut_name= '全プロセス' and cut_name='恐慌')
(id=3) and ( cut_name='全プロセス' or cut_name='恐慌')
select * from emovis_reporting
    where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') OR
        ( (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') )
SELECT * FROM table1 NATURAL JOIN table2;