使用此标准作者/书籍设置:
CREATE TABLE authors (
id int NOT NULL,
name varchar(255) NOT NULL
)
CREATE TABLE books (
id int NOT NULL,
name varchar(255) NOT NULL,
author_id int NOT NULL,
sold int NOT NULL
)
INSERT INTO authors VALUES (1, 'author 1')
INSERT INTO authors VALUES (2, 'author 2')
INSERT INTO books VALUES (1, 'book 1', 1, 10)
INSERT INTO books VALUES (2, 'book 2', 1, 5)
INSERT INTO books VALUES (3, 'book 3', 2, 7)
此查询以某种方式不起作用:
SELECT
(
SELECT
count(*)
FROM
(
SELECT
books.name
FROM
books
WHERE
books.author_id = authors.id
AND books.sold > (
SELECT
avg(sold)
FROM
books
WHERE
books.author_id <> authors.id
)
) AS t
) AS good_selling_books
FROM
authors
WHERE
authors.id = 1
错误消息是:
SQL0204N“AUTHORS.ID”是未定义的名称。 SQLSTATE = 42704
看起来DB2在子查询中深入3级后失去了对最外层表的跟踪?
注意:这只是一个伪造的查询,所以它可能没有多大意义(并且可以很容易地重写为只有2级嵌套,这可以正常工作)。我只想确认DB2是否确实存在这样一个明显的缺点。
答案 0 :(得分:1)
刚刚找到了相当简单的解决方案。 DB2具有此LATERAL
关键字,此类查询可用于此工作,例如
SELECT
(
SELECT
count(*)
FROM
LATERAL( -- this is the only change
SELECT
books.name
FROM
books
WHERE
books.author_id = authors.id
AND books.sold > (
SELECT
avg(sold)
FROM
books
WHERE
books.author_id <> authors.id
)
) AS t
) AS good_selling_books
FROM
authors
WHERE
authors.id = 1
解决方案来自这篇博文https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/scoping_rules_in_db2125?lang=en,其中作者也注意到了DB2中的相同缺点:
但是DB2也没有跳到S.c1两级。我想它可以但是,唉,它没有。
答案 1 :(得分:0)
问题是最里面的查询。 如果没有FROM子句中的作者,则不能只与authors.id进行比较。
答案 2 :(得分:0)
在MySQL中也出现了完全相同的错误:
ERROR 1054 (42S22): Unknown column 'authors.id' in 'where clause'
我怀疑查询确实不正确。我相信您需要在最内层查询的authors
子句中引用FROM
表。我最近做了很多NOSQL的事情,所以我的SQL查询技巧有点尘土飞扬,但我很确定内部查询无法将 out 传递给其他表。
如果可以,使用连接而不是嵌套查询重写查询。嵌套查询的性能无论如何都倾向于优化(在DB2中未经证实,但至少在MySQL 5.1中是如此)。