在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 JOIN
或WHERE 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 JOIN
和DISTINCT
的MySQL替代方法:
SELECT DISTINCT value FROM table_a INNER JOIN table_b USING (value); +-------+ | value | +-------+ | B | +-------+
另一个例子使用WHERE ... IN
和DISTINCT
:
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);