Question

I'm trying to execute seemingly simple request contains WITH clause:

WITH sub AS (SELECT url FROM site WHERE id = 15) 
SELECT * FROM search_result WHERE url = sub.url

But it doesn't work. I get

ERROR: missing FROM-clause entry for table "sub"

What's the matter?

Was it helpful?

Solution

Table expressions need to be used like tables. You're trying to use the value of sub as a scalar.

Try this (forgive me, Postgres is not my first SQL dialect).

WITH sub AS (SELECT url FROM site WHERE id = 15) 
SELECT * FROM sub
INNER JOIN
 search_result 
ON
  sub.url = search_result.url

EDIT, alternatively, you could just skip the WITH clause and go with:-

SELECT * FROM 
  site
INNER JOIN
  search_result 
ON
  site.url = search_result.url
WHERE 
  site.id = 15

OTHER TIPS

Don't use a CTE at all for this simple case. Unlike you seem to be expecting, the following simple query without a CTE will be slightly faster:

SELECT r.*
FROM   search_result r
JOIN   site s USING (url)
WHERE  s.id = 15;

Test with EXPLAIN ANALYZE to verify.

CTEs introduce an optimization barrier. They have many very good uses, but they won't make simple queries faster. Here is a thread on pgsql-performance that gives you more details as to why that is.

That's not the correct way to use a CTE:

With sub as (
    SELECT url
    FROM site
    WHERE id = 15
)
SELECT * 
FROM Search_Result SR 
   JOIN sub ON SR.url = sub.Url

You can just as easily do an inner join:

SELECT search_result .* 
FROM
    search_result
INNER JOIN
    (SELECT url FROM site WHERE id = 15) as st
ON
    search_result.url = st.url

This does the filtering so that you are joining on a smaller set than if you did the where clause outside of the filtering. This may not matter in your case, but it is something to consider.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top