在将3个级别深入子查询后,DB2将丢失对表的跟踪

时间:2011-08-19 10:41:07

标签: db2 subquery

使用此标准作者/书籍设置:

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是否确实存在这样一个明显的缺点。

3 个答案:

答案 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中是如此)。