涉及两个联接的SQL查询中的歧义

时间:2018-09-20 09:09:31

标签: mysql sql

我有三个表,其结构如下:

results:
id | url_id

foo
id | url_id | url

bar
id | url_id | url

我希望能够在单个查询中选择该URL,因为它知道可能在任何一个表中。

我的计划是在两个表上都做一个LEFT JOIN,然后返回类似IFNULL(foo.url, bar.url) as url的内容。

将结果称为url很重要。

但是,由于含糊不清,我无法在我的url子句中使用相同的WHERE列名。这是我的查询和收到的错误消息:

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

选择其他名称的列并在我的代码中将其重命名是相当琐碎的,但是在SQL中这样做会更好。

这是一个SQL提琴:http://sqlfiddle.com/#!9/32abc6/4

欢呼

5 个答案:

答案 0 :(得分:2)

您不能使用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 子句的SELECT子句中声明的别名,因为WHERE发生在WHERE之前。

因此:

SELECT

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;

答案 1 :(得分:1)

您的问题的直接答案是在引用列时使用表别名。我将其写为一系列的左联接:

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;

此答案假设实际的url匹配项可能在任何一个表中,或者,如果两者都匹配,则您不介意从foo表中获取版本。

答案 2 :(得分:1)

如果相同的列名可用于多个表,则您的错误建议使用表别名:

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 = ?;

这会回答您的-> Column 'url' in where clause is ambiguous错误,如果如此,JOIN可能与您想要的不一样,然后调整on子句或为JOIN提供其他条件。但是使用别名来简化查询或编译器的想法是相同的。

答案 3 :(得分:1)

如果您想在可以使用子查询的位置使用url,则这两个表都具有url列,但是您只写了一个,因此要么必须在其中使用table.column名称

..., 'DIAPER-BE SURE-M 5''s', ...

答案 4 :(得分:0)

所以你有

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

抱歉的解决方案是使用:

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

效率不应该降低。这是一个人付出的。 也许以下方法会起作用:

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

引入表别名以消除歧义。