替代MySQL中的Intersect

时间:2010-04-12 10:44:34

标签: 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='恐慌') )

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

8 个答案:

答案 0 :(得分:54)

Microsoft SQL Server的INTERSECT “返回INTERSECT操作数左侧和右侧的查询返回的所有不同值”这与标准{{1>不同}或INNER JOIN查询。

SQL Server

WHERE EXISTS

<强>的MySQL

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)

对于这个特殊问题,涉及id列,因此不会返回重复值,但为了完整起见,这里是使用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 | +-------+ INNER JOIN的MySQL替代方案:

DISTINCT

另一个使用SELECT DISTINCT value FROM table_a INNER JOIN table_b USING (value); +-------+ | value | +-------+ | B | +-------+ WHERE ... IN的示例:

DISTINCT

答案 1 :(得分:37)

通过使用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;

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

答案 2 :(得分:15)

您的查询将始终返回空记录集,因为cut_name= '全プロセス' and cut_name='恐慌'永远不会评估为true

通常,INTERSECT中的MySQL应该像这样模仿:

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
        )

答案 3 :(得分:3)

我刚刚在MySQL 5.7中检查了它,我真的很惊讶没有人提供一个简单的答案:NATURAL JOIN

当表格或(选择结果)具有IDENTICAL列时,您可以使用NATURAL JOIN作为查找交集的方式:

enter image description here

例如:

<强>表1

id,name,jobid

'1','John','1'

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

'3','Adam','2'

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

<强>表2

id,name,jobid

'1','John','1'

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

'3','Adam','2'

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

'5','Max','6'

以下是查询:

SELECT * FROM table1 NATURAL JOIN table2;

查询结果:  id,name,jobid

'1','John','1'

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

'3','Adam','2'

答案 4 :(得分:1)

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

通常用于名为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生成Cartesian product

此处的INNER JOIN会从您的表中生成每个permutation个行对。这意味着以各种可能的顺序生成行的每个组合。然后,WHERE子句会过滤a一侧,然后过滤b一侧。结果是只返回满足两个条件的行,就像交叉两个查询一样。

答案 5 :(得分:0)

在2个陈述中打破你的问题:首先,你要选择所有

-

是真的。其次,你想要选择所有

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

是真的。因此,我们将通过OR加入两者,因为如果其中任何一个都是真的我们想要选择所有。

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

答案 6 :(得分:-2)

AFAIR,MySQL通过INNER JOIN实现INTERSECT。

答案 7 :(得分:-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);