web-dev-qa-db-fra.com

Avec ... comme la déclaration ne fonctionne pas comme prévu

Je reçois cette erreur:

WITH...AS syntax error

Il se pose quand j'essaie d'exécuter la requête suivante:

with expensive_service as (
    select s1.*
    from service s1, service s2
    where s1.price > s2.price
)
select * 
from service except expensive_service;

J'essayais de mettre en œuvre WITH ... AS (lien vers les documents PostgreSQL).

Cette requête me donne la sortie souhaitée que je recherche:

select * 
from service except ( 
    select s1.*
    from service s1, service s2
    where s1.price > s2.price
)

Toute aide me dirigeant où l'erreur réside serait grandement appréciée!

2
FernandoH-G

Le CTE (expression de table commune) est comme une vue et vous devez le traiter comme n'importe quelle autre vue (ou table). Vous avez besoin d'une déclaration de sélection complète comme deuxième partie de l'exception:

with expensive_service as (
    select s1.*
    from service s1, service s2
    where s1.price > s2.price
)
select * 
from service 
except 
select *
from expensive_service;

Notez que des parenthèses autour des différentes parties d'une union, sauf ou intersect ne sont pas nécessaires (sauf si vous avez besoin d'une commande par pour seulement cette requête, par exemple parce que vous utilisez une clause limite).

Donc, votre requête d'origine pourrait (devrait à mon avis) aussi être écrite comme

select * 
from service 
except  
select s1.*
from service s1, service s2
where s1.price > s2.price
7

Cette requête me donne la sortie souhaitée que je recherche:

Utilisez ceci à la place!

SELECT *
FROM   service
WHERE  price = (SELECT min(price) FROM service)
-- OR  price IS NULL  -- add if price can be NULL

Assurez-vous d'avoir un index sur (price) Si votre table est grande.

La réponse actuellement acceptée a de bonnes informations techniques, mais la requête ne doit jamais être utilisée. En outre, vous voudriez généralement EXCEPT ALL au lieu de EXCEPT. Voir:

Mais ne le fais pas.

Pourquoi?

La implicite CROSS JOIN Dans la deuxième SELECT échelles avec O (N²) . Qu'est ce que ça fait?

...
SELECT s1.*
FROM   service s1, service s2
WHERE  s1.price > s2.price

Cela renvoie une copie de chaque ligne pour chaque ligne de la table avec un plus petit price (ou où price IS NULL). Pourquoi? Exclure ceux de la prochaine étape. Ce qui signifie, seules des lignes avec le plus petit prix (ou price IS NULL) sont pas exclu. En d'autres termes:

Obtenez toutes les lignes avec le minimum price (ou price IS NULL).

En rapport:

2