2

I get this error:

WITH...AS syntax error

It arises when I try to execute the following query:

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

I was trying to implement WITH ... AS (link to PostgreSQL docs).

This query gives me the desired output I'm looking for:

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

Any aid directing me where the error lies would be greatly appreciated!

3
  • We kindly ask to present text as text, not screenshots. Screenshots are blackboxes that deny copy/paste and cannot be searched for. Also please remember to disclose your version of Postgres. Always helpful, sometimes essential. And please explain what your query should do, in plain English. I have reason to believe you want a different query ... Apr 3, 2020 at 21:16
  • @ErwinBrandstetter Roger. Will keep those tips in mind for next time. The postgres verson I'm using is psql 12.2, server 11.5, AWS RDS. My query was looking to find the least expensive product via its price. Apr 3, 2020 at 22:55
  • Seems to match what I deduced: Get all rows with the minimum price. Compare performance with EXPLAIN ANALYZE ... BTW, table definition (CRATE TABLE statement showing data types and constraints) is always instrumental, too. Apr 3, 2020 at 23:45

2 Answers 2

7

The CTE (common table expression) is like a view and you need to treat it like any other view (or table). You need a complete SELECT statement as the second part of the EXCEPT:

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

Note that parentheses around the individual parts of a UNION, EXCEPT or INTERSECT are not needed (unless you need an ORDER BY for only that query, e.g. because you are using a LIMIT clause).

So your original query could (should in my opinion) also be written as

select * 
from service 
except  
select s1.*
from service s1, service s2
where s1.price > s2.price
1
  • Thank you very much! That answered my question and then some. Mar 23, 2020 at 7:41
2

This query gives me the desired output I'm looking for:

Use this instead!

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

Be sure to have an index on (price) if your table is big.

The currently accepted answer has good technical information, but the actual query should never be used. Also, you would typically want EXCEPT ALL instead of EXCEPT. See:

But don't.

Why?

The implicit CROSS JOIN in the second SELECT scales with O(N²). What does it do?

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

This returns one copy of every row for every other row in the table with a smaller price (or where price IS NULL). What for? To exclude those in the next step. Meaning, only rows with the smallest price (or price IS NULL) are not excluded. In other words:

Get all rows with the minimum price (or price IS NULL).

Related:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.