在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='恐慌') ) 

我知道相交不在MySQL中。 所以我需要另一种方式。 请指导我

Microsoft SQL Server的INTERSECT “返回由INTERSECT操作数的左侧和右侧的查询返回的任何不同的值”这与标准的INNER JOINWHERE EXISTS查询不同。

SQL Server

 CREATE TABLE table_a ( id INT PRIMARY KEY, value VARCHAR(255) ); CREATE TABLE table_b ( id INT PRIMARY KEY, value VARCHAR(255) ); INSERT INTO table_a VALUES (1, 'A'), (2, 'B'), (3, 'B'); INSERT INTO table_b VALUES (1, 'B'); SELECT value FROM table_a INTERSECT SELECT value FROM table_b value ----- B (1 rows affected) 

MySQL的

 CREATE TABLE `table_a` ( `id` INT NOT NULL AUTO_INCREMENT, `value` varchar(255), PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE `table_b` LIKE `table_a`; INSERT INTO table_a VALUES (1, 'A'), (2, 'B'), (3, 'B'); INSERT INTO table_b VALUES (1, 'B'); SELECT value FROM table_a INNER JOIN table_b USING (value); +-------+ | value | +-------+ | B | | B | +-------+ 2 rows in set (0.00 sec) SELECT value FROM table_a WHERE (value) IN (SELECT value FROM table_b); +-------+ | value | +-------+ | B | | B | +-------+ 

有了这个特定的问题,id列被涉及,所以重复的值将不会被返回,但为了完整起见,这里是一个使用INNER JOINDISTINCT的MySQL替代方法:

 SELECT DISTINCT value FROM table_a INNER JOIN table_b USING (value); +-------+ | value | +-------+ | B | +-------+ 

另一个例子使用WHERE ... INDISTINCT

 SELECT DISTINCT value FROM table_a WHERE (value) IN (SELECT value FROM table_b); +-------+ | value | +-------+ | B | +-------+ 

通过使用UNION ALL和GROUP BY,有一种更有效的方法来生成相交。 根据我在大型数据集上的testing,性能会好两倍。

例:

 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; 

这是更有效的,因为使用INNER JOIN解决scheme,MySQL将查找第一个查询的结果,然后对于每一行,在第二个查询中查找结果。 使用UNION ALL-GROUP BY解决scheme,它将查询第一个查询的结果,第二个查询的结果,然后将所有结果一起分组。

您的查询将始终返回一个空logging集,因为cut_name= '全プロセス' and cut_name='恐慌'永远不会计算为true

一般来说, 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)) ) 

如果两个表都有标记为NOT NULL列,则可以省略IS NULL部分,并用更高效的IN重写查询:

 SELECT * FROM mytable m WHERE (col1, col2, col3) IN ( SELECT col1, col2, col3 FROM othertable o ) 

为了完整,这里是另一种模拟INTERSECT方法。 请注意,其他答案中build议的IN (SELECT ...)forms通常更有效。

通常对于名为mytable的表,其主键为id

 SELECT id FROM mytable AS a INNER JOIN mytable AS b ON a.id = b.id WHERE (a.col1 = "someval") AND (b.col1 = "someotherval") 

(请注意,如果您在此查询中使用SELECT * ,将获得mytable中定义的两倍的列,这是因为INNER JOIN生成笛卡尔积 )

这里的INNER JOIN从你的表中生成行对的每个排列 。 这意味着每一行的组合都是按照每一个可能的顺序生成的。 WHERE子句然后过滤一对a一侧,然后过滤b侧。 结果是只有满足这两个条件的行才被返回,就像两个查询的交集一样。

打破你的问题在两个陈述:首先,你要select所有如果

 (id=3 and cut_name= '全プロセス' and cut_name='恐慌') 

是真的 。 其次,你要select全部如果

 (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') 

是真的。 因此,我们将通过OR来join,因为如果其中任何一个都是真的,我们就要select它们。

 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中检查它,真的很惊讶没有人提供一个简单的答案:NATURAL JOIN

当表或(select结果)具有IDENTICAL列时,可以使用NATURAL JOIN作为find相交的方法:

在这里输入图像描述

例如:

表1

ID,名字,工作

'1','约翰','1'

'2','杰克','3'

'3','亚当','2'

'4','比尔','6'

表2

ID,名字,工作

'1','约翰','1'

'2','杰克','3'

'3','亚当','2'

'4','比尔','5'

'5','Max','6'

这里是查询:

 SELECT * FROM table1 NATURAL JOIN table2; 

查询结果: id,name,jobid

'1','约翰','1'

'2','杰克','3'

'3','亚当','2'

AFAIR,MySQL通过INNER JOIN实现INTERSECT。

 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);