简体   繁体   中英

Ambiguity in an SQL query involving two joins

I have three tables that are structured as follows:

results:
id | url_id

foo
id | url_id | url

bar
id | url_id | url

I want to be able to select the URL in a single query knowing that it could be in either table.

My plan was to do a LEFT JOIN on both of the tables and then return something like IFNULL(foo.url, bar.url) as url .

It is important that the result is called url .

However, I cannot use this same url column name in my WHERE clause because of the ambiguity. Here is my query and the error message I get:

SELECT r.id,
COALESCE(foo.url, bar.url) as url
FROM results r
LEFT JOIN foo USING (url_id)
LEFT JOIN bar USING (url_id)
WHERE url IS NOT NULL;

Column 'url' in where clause is ambiguous

It would be fairly trivial to select the column under a different name and rename it in my code, but it would be nicer to do it in SQL.

Here is an SQL Fiddle: http://sqlfiddle.com/#!9/32abc6/4

Cheers

You cannot use an alias name declared in the SELECT clause in your WHERE clause, because WHERE happens before SELECT .

Hence:

SELECT r.id, COALESCE(foo.url, bar.url) as url
FROM results r
LEFT JOIN foo USING (url_id)
LEFT JOIN bar USING (url_id)
WHERE COALESCE(foo.url, bar.url) IS NOT NULL;

or

SELECT r.id, COALESCE(foo.url, bar.url) as url
FROM results r
LEFT JOIN foo USING (url_id)
LEFT JOIN bar USING (url_id)
WHERE foo.url IS NOT NULL OR bar.url IS NOT NULL;

The direct answer to your question is to use table aliases when referring to columns. I would write this as a series of left joins:

SELECT
    r.id,
    r.url_id,
    COALESCE(f.url, b.url) AS url
FROM results r
LEFT JOIN foo f
    ON r.url_id = f.url_id
LEFT JOIN bar b
    ON r.url_id = b.url_id;

This answer assumes that the actual url match could be in either table, or, if it matches to both, then you don't mind taking the version from the foo table.

Your error suggests to use table alias if same column name available with more than one table :

select f.id, ifnull(b.url, f.url) as url
from foo f left join
     bar b
     on b.id = f.id
where f.url_id = ?;

This answers your -> Column 'url' in where clause is ambiguous error, JOIN s may not same as you want if so then adjust the on clause or provide one other conditions with JOIN . But the idea would be same to use alias to make it easier to understand the query or to compiler.

if you want url on where you can use sub-query cause your both table has url column but you make one so either you have to use table.column name in where

select * from 
(
  SELECT r.id,
COALESCE(foo.url, bar.url) as url
FROM results r
LEFT JOIN foo USING (url_id)
LEFT JOIN bar USING (url_id)
)as t where t.url is NOT NULL

So you have

SELECT ..., IFNULL(foo.url, bar.url) AS url
...
WHERE url LIKE ?      *** Error: "url" ambiguous

The sorry solution is to use:

SELECT ..., IFNULL(foo.url, bar.url) AS url
...
WHERE IFNULL(foo.url, bar.url) LIKE ?

It should not be less efficient. It is what one pays. Maybe the following would work:

SELECT ..., z.url
FROM (SELECT IFNULL(foo.url, bar.url) AS url FROM DUAL AS z)
JOIN ...
WHERE z.url LIKE ?

Introducing a table alias for disambiguation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM