2011-08-19 1 views
1

に3つのレベルを取得した後、テーブルのトラックを失う:DB2は、この規格作者/ブックのセットアップで深いサブクエリ

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" is an undefined name. SQLSTATE=42704

サブクエリに3レベルの深さを与えた後にDB2が最も外側のテーブルのトラックを失うようですか?

注:これは単なる作成されたクエリなので、あまり意味がないかもしれません(そして、うまく動作する2つのレベルのネストしか持たないように簡単に書き換えられます)。私はちょうどDB2が本当にそのような目立つ欠点を持っているかどうかを確認したい。

答えて

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 

ソリューションは、著者はまた、DB2と同じ欠点に気づいこのブログ記事https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/scoping_rules_in_db2125?lang=en、から来た:

But DB2 also didn't jump two levels up to S.c1. I suppose it could but, alas, it does not.

0

問題は最も内側のクエリです。 authors.idと比較することはできません.FROM句に作者を追加する必要はありません。

+0

+1ポスターは彼のスコープが混ざっています。 Subselectはスタンドアロンのステートメントで、その結果は外側の選択にさらされます。 – Eddy

+0

@Eddyこれを私よりも明示的に指摘してくれてありがとう。 – Ingo

+0

これは意味をなさない。なぜ2番目の最も内側のauthors.idはそれで動作しますか?ちなみに、クエリはPostgreSQLとSQL Serverで完全に正常に動作します。 – sayap

0

また、これは正確に同じエラーでのMySQLに失敗:

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

私は、クエリが実際に間違っていると思われるでしょう。最も内側のクエリのFROM句のauthorsテーブルへの参照が必要だと思います。私は最近、多くのNOSQLのことをやっているので、私のSQLクエリのスキルはちょっとダストですが、内側のクエリが他のテーブルにのに届かないと確信しています。

可能であれば、ネストされたクエリの代わりに結合を使用してクエリを書き換えます。ネストされたクエリのパフォーマンスは、とにかく(MySQLでは実証されていませんが、少なくともMySQL 5.1では真実です)ほとんど最適化されません。

+0

私は実際には、クエリがMySQLで動作しないことは非常に驚いています。参考までに、PostgreSQLとSQL Serverでは正常に動作します。とにかく、「内側のクエリが他のテーブルに到達できない」という部分は間違っています。 'SELECT a.key(SELECT count(*)FROM b WHERE b.key = a.key)のようなクエリはASから集計します.'はどんなデータベースでもうまく動作します。 – sayap

+0

サブクエリが 'FROM'節にあるときに動作しますか? –

関連する問題