60 votes

Alternative à intersection dans MySQL

J'ai besoin d'implémenter la requête suivante dans 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='恐慌') )
 

Je sais que l'intersection n'est pas dans MySQL. J'ai donc besoin d'un autre moyen. Guidez-moi s'il-vous-plaît.

55voto

Mike Points 11170

Microsoft SQL Server INTERSECT "renvoie toutes les valeurs distinctes qui sont renvoyées par les requêtes sur les côtés gauche et droit de l'opérande INTERSECT" C'est différent d'une norme INNER JOIN ou WHERE EXISTS de la requête.

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

Avec cette question en particulier, la colonne id est impliquée, de sorte que les valeurs en double ne seront pas retournés, mais par souci d'exhaustivité, voici un MySQL alternative à l'aide de INNER JOIN et DISTINCT:

SELECT DISTINCT value FROM table_a
INNER JOIN table_b
USING (value);

+-------+
| value |
+-------+
| B     |
+-------+

Et un autre exemple d'utilisation WHERE ... IN et DISTINCT:

SELECT DISTINCT value FROM table_a
WHERE (value) IN
(SELECT value FROM table_b);

+-------+
| value |
+-------+
| B     |
+-------+

38voto

FBB Points 292

Il y a un moyen plus efficace de générer une intersection, en utilisant de l'UNION de TOUS et de GROUPE. Les Performances sont deux fois mieux selon mes tests sur de grands ensembles de données.

Exemple:

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

Il est plus efficace, car avec la JOINTURE INTERNE de la solution, MySQL va chercher les résultats de la première requête, puis pour chaque ligne, regarder le résultat dans la deuxième requête. Avec l'UNION de TOUS les GROUPE EN solution, il aura les résultats de la requête de la première requête, les résultats de la deuxième requête, puis regrouper les résultats de tous ensemble à la fois.

15voto

Quassnoi Points 191041

Votre requête renverra toujours un jeu d'enregistrements vide, car cut_name= '全プロセス' and cut_name='恐慌' ne sera jamais évalué à true .

En général, INTERSECT en MySQL devrait être imité de la manière suivante:

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

Si les colonnes de vos deux tables sont marquées comme NOT NULL , vous pouvez omettre les parties IS NULL et réécrire la requête avec un IN légèrement plus efficace:

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

1voto

RobM Points 2681

Pour être complet, voici une autre méthode pour l'émulation INTERSECT. Notez que l' IN (SELECT ...) formulaire suggéré dans d'autres réponses est généralement plus efficace.

En général, pour une table appelée mytable avec une clé primaire appelés 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")

(Notez que si vous utilisez SELECT * avec cette requête, vous obtiendrez deux fois autant de colonnes que sont définies en mytable, c'est parce qu' INNER JOIN génère un produit Cartésien)

L' INNER JOIN ici génère chaque permutation de lignes paires à partir de votre tableau. Cela signifie que chaque combinaison de lignes est généré, dans chaque ordre possible. L' WHERE clause filtres de l' a côté de la paire, puis l' b côté. Le résultat est que seules les lignes qui satisfont les deux conditions sont retournés, tout comme intersection de deux requêtes ne.

-2voto

deklin Points 154

AFAIR, MySQL implémente INTERSECT via INNER JOIN .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X