MySQL中的交集替代方法

nhaq1z21  于 2022-10-31  发布在  Mysql
关注(0)|答案(9)|浏览(111)

我需要在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中。所以我需要另一种方法。请指导我。

9njqaruj

9njqaruj1#

Microsoft SQL Server的INTERSECT“会传回INTERSECT算子左右两侧的查询所传回的任何相异值” 这与标准的INNER JOINWHERE EXISTS查询不同。

SQL服务器

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     |
+-------+
b1uwtaje

b1uwtaje2#

有一种更有效的方法可以生成交集,那就是使用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解决方案,它将查询第一个查询的结果,第二个查询的结果,然后将所有结果一次组合在一起。

qoefvg9y

qoefvg9y3#

由于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
        )
g0czyy6m

g0czyy6m4#

我刚刚在MySQL 5.7中检查了它,真的很惊讶为什么没有人提供一个简单的答案:自然接合
当表或(选择结果)具有IDENTICAL列时,可以使用NATURAL JOIN作为查找交集的一种方法:

例如:

表格1

ID、名称、作业ID
'1','约翰','1'
'2','杰克','3'
'3','亚当','2'
'4','账单','6'

表格2

ID、名称、作业ID
'1','约翰','1'
'2','杰克','3'
'3','亚当','2'
'4','账单','5'
'5','最大值','6'
下面是查询:

SELECT * FROM table1 NATURAL JOIN table2;

**查询结果:**标识,名称,作业标识

'1','约翰','1'
'2','杰克','3'
'3','亚当','2'

frebpwbc

frebpwbc5#

为了完整起见,这里提供了另一种模拟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")

(Note如果将SELECT *与此查询一起使用,则得到的列数将是mytable中定义的列数的两倍,这是因为INNER JOIN生成笛卡尔积)
这里的INNER JOIN生成表中行对的每个排列。这意味着以每个可能的顺序生成行的每个组合。然后WHERE子句过滤行对的a侧,然后是b侧。结果是只返回同时满足两个条件的行,就像交集两个查询所做的那样。

2uluyalo

2uluyalo6#

用两句话来解释你的问题:首先,如果

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

为true。其次,如果

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

是真的。所以,我们将通过OR连接两者,因为如果其中任何一个为真,我们将选择全部。

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

eaf3rand7#

从MySQL 8.0.31开始,INTERSECT本身就受支持。
INTERSECT Clause
选择...相交[全部|区分]选择... [交叉[全部|区分]选择...]
INTERSECT将多个SELECT语句的结果限制为所有语句共有的那些行。
样品:

SELECT 1 AS col
 INTERSECT 
 SELECT 1 AS col;

 -- output
 1
pvabu6sv

pvabu6sv8#

AFAIR,MySQL通过INNER JOIN实现了INTERSECT。

yrwegjxp

yrwegjxp9#

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

相关问题