DB2 теряет контроль над таблицей после 3-х уровней вглубь подзапроса - PullRequest
1 голос
/ 19 августа 2011

При такой стандартной настройке авторов / книг:

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 ]

1 голос
/ 22 августа 2011

Только что нашел решение, которое довольно просто. У 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. Я полагаю, что может, но, увы, нет.

0 голосов
/ 19 августа 2011

Это также дает сбой в MySQL с точно такой же ошибкой:

ERROR 1054 (42S22): Unknown column 'authors.id' in 'where clause'

Я подозреваю, что запрос действительно неверен. Я считаю, что вам нужна ссылка на таблицу authors в предложении FROM самого внутреннего запроса. В последнее время я много занимался NOSQL, поэтому мои навыки SQL-запросов немного запылены, но я уверен, что внутренний запрос не может достичь из других таблиц.

Перепишите запрос, используя объединения, а не вложенные запросы, если можете. Производительность вложенных запросов в любом случае имеет тенденцию к плохой оптимизации (необоснованно в DB2, но верно как минимум в MySQL 5.1).

0 голосов
/ 19 августа 2011

Проблема - самый внутренний запрос. Вы не можете просто сравнить с author.id без авторов в предложении FROM.

...