21 votes

Comment réécrire une clause IN multi-colonnes pour qu'elle fonctionne sur SQLite ?

J'ai une requête qui ressemble à quelque chose comme ça :

SELECT
  *
FROM table
WHERE
  (col1, col2) in (
    ('col1_val1', 'col2_val1'),
    ('col1_val2', 'col2_val2'),
    ('col1_val3', 'col2_val3'),
  )

Cela fonctionne dans MySQL, mais échoue dans sqlite3 avec une erreur de syntaxe :

Error: near ",": syntax error

Comment puis-je réécrire cette requête en une requête équivalente qui fonctionne dans sqlite3 ?

14voto

biziclop Points 9290

Choisissez votre version préférée :

http://sqlfiddle.com/#!5/6169b/9

utilisation d'une table temporaire

CREATE TEMPORARY TABLE pair (a INTEGER, b INTEGER);
INSERT INTO pair (a, b) VALUES (1, 1);
INSERT INTO pair (a, b) VALUES (2, 2);
....

données DANS des paires ; si la paire(a,b) n'est pas unique

SELECT *
FROM data
WHERE EXISTS (
  SELECT NULL
  FROM  pair
  WHERE pair.a = data.a
    AND pair.b = data.b
);

données en paires ; si la paire (a,b) est unique

SELECT     data.*
FROM       data
INNER JOIN pair
        ON pair.a = data.a
       AND pair.b = data.b;

données NOT IN pairs ; si paire(a,b) est unique

SELECT    data.*
FROM      data
LEFT JOIN pair
   ON pair.a = data.a
  AND pair.b = data.b
WHERE pair.a IS NULL
   OR pair.b IS NULL;

utiliser un tableau en ligne

données DANS des paires ; si la paire(a,b) n'est pas unique

SELECT *
FROM data
WHERE EXISTS (
  SELECT NULL
  FROM  (
    SELECT 1 AS a, 1 AS b
    UNION ALL
    SELECT 2 AS a, 2 AS b
    UNION ALL
    SELECT 3 AS a, 3 AS b
  ) AS pair
  WHERE pair.a = data.a
    AND pair.b = data.b
);

données en paires ; si la paire (a,b) est unique

SELECT     data.*
FROM       data
INNER JOIN (
  SELECT 1 AS a, 1 AS b
  UNION ALL
  SELECT 2 AS a, 2 AS b
  UNION ALL
  SELECT 3 AS a, 3 AS b
) AS pair
 ON  pair.a = data.a
AND  pair.b = data.b;

données NOT IN pairs ; si paire(a,b) est unique

SELECT    data.*
FROM      data
LEFT JOIN (
  SELECT 1 AS a, 1 AS b
  UNION ALL
  SELECT 2 AS a, 2 AS b
  UNION ALL
  SELECT 3 AS a, 3 AS b
 ) AS pair
   ON pair.a = data.a
  AND pair.b = data.b
WHERE pair.a IS NULL
   OR pair.b IS NULL;

10voto

Johannes Fahrenkrug Points 12795

Voici une solution facile qui fonctionne, mais qui risque de ne pas être très performante sur les grands ensembles de données car elle ne peut utiliser aucun de vos index.

SELECT * FROM table
WHERE col1 || '-' || col2 in (
  'col1_val1-col2_val1',
  'col1_val2-col2_val2',
  'col1_val3-col2_val3'
)

Essayez-le dans sqlfiddle

Profitez-en !

7voto

Stevelot Points 119

Dans sqlite, essayez d'ajouter le mot clé VALUES :

SELECT *
FROM table
WHERE
  (col1, col2) in ( VALUES     --> add this keyword and remove the last ,
    ('col1_val1', 'col2_val1'),
    ('col1_val2', 'col2_val2'),
    ('col1_val3', 'col2_val3')
  )

En fait, dans sqLite, on exécute la requête :

VALUES
('col1_val1', 'col2_val1'),
('col1_val2', 'col2_val2');

est la même chose que :

SELECT 'col1_val1' AS column1, 'col2_val1' AS column2
UNION 
SELECT 'col1_val2' AS column1, 'col2_val2' AS column2;

ou combinés :

SELECT 'col1_val1' AS column1, 'col2_val1' AS column2
UNION  VALUES  ('col1_val2', 'col2_val2');

Donc vous pourriez même l'écrire comme :

SELECT * 
  FROM table
  WHERE (col1, col2) IN ( 
      SELECT 'col1_val1', 'col2_val1'
      UNION 
      SELECT 'col1_val2', 'col2_val2'
  );

qui est une sous-requête simple et fonctionne dans toutes/la plupart des bases de données.

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