web-dev-qa-db-fra.com

Comment utiliser plusieurs instructions WITH dans une requête PostgreSQL?

Je voudrais "déclarer" quels sont effectivement plusieurs tables TEMP en utilisant l'instruction WITH. La requête que j'essaie d'exécuter va dans le sens de:

WITH table_1 AS (
SELECT GENERATE_SERIES('2012-06-29', '2012-07-03', '1 day'::INTERVAL) AS date
)

WITH table_2 AS (
SELECT GENERATE_SERIES('2012-06-30', '2012-07-13', '1 day'::INTERVAL) AS date
)

SELECT * FROM table_1
WHERE date IN table_2

J'ai lu documentation PostgreSQL et effectué des recherches pour utiliser plusieurs instructions WITH et je suis incapable de trouver une réponse.

54
Greg

Selon les autres commentaires, la deuxième expression de table commune [CTE] est précédée d’une virgule et non d’une instruction WITH,

WITH cte1 AS (SELECT...)
, cte2 AS (SELECT...)
SELECT *
FROM
    cte1 c1
    INNER JOIN cte2 c2
    ON ........

Pour ce qui est de votre requête, cette syntaxe devrait fonctionner dans PostgreSql, Oracle et sql-server. Bien plus tard, vous procéderez généralement WITH avec un point-virgule (;WTIH), mais cela est dû au fait que les employés de serveur SQL (moi-même inclus) ne terminent pas les instructions précédentes qui doivent être terminées avant la définition d'un CTE ...

Notez cependant que vous avez eu un deuxième problème de syntaxe en ce qui concerne votre instruction WHERE. WHERE date IN table_2 n'est pas valide car vous ne faites jamais référence à une valeur/colonne de table_2. Je préfère INNER JOIN over IN ou Exists alors voici une syntaxe qui devrait fonctionner avec un JOIN:

WITH table_1 AS (
SELECT GENERATE_SERIES('2012-06-29', '2012-07-03', '1 day'::INTERVAL) AS date
)

, table_2 AS (
SELECT GENERATE_SERIES('2012-06-30', '2012-07-13', '1 day'::INTERVAL) AS date
)

SELECT * 
FROM
     table_1 t1
     INNER JOIN 
     table_2 t2
     ON t1.date = t2.date
;

Si vous voulez conserver ce que vous aviez, ce qui est généralement EXISTS serait meilleur qu'IN, mais pour utiliser IN, vous avez besoin d'une instruction SELECT réelle dans votre où.

SELECT * 
FROM
     table_1 t1
WHERE t1.date IN (SELECT date FROM table_2);

IN est très problématique quand date pourrait potentiellement être NULL donc si vous ne voulez pas utiliser un JOIN, je vous suggérerais donc EXISTS. Comme suit:

SELECT * 
FROM
     table_1 t1
WHERE EXISTS (SELECT * FROM table_2 t2 WHERE t2.date = t1.date);
93
Matt