2011-08-19 23 views
1

有了這個標準的作者/書籍安裝後會失去跟蹤表:DB2獲得3個層次進深一子查詢

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

看起來像DB2在進入子查詢3層後失去了最外層表的蹤跡嗎?

注意:這只是一個捏造的查詢,所以它可能沒有多大意義(並且可以很容易地被重寫爲只有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 

該解決方案來自這個博客帖子https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/scoping_rules_in_db2125?lang=en,在這裏筆者也注意到了同樣的缺點在DB2:

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

0

問題是最內層的查詢。 如果沒有FROM子句中的作者,則不能僅將其與authors.id進行比較。

+0

+1海報上有他的作用域混合起來。子選擇是獨立的語句,其結果暴露給外部選擇而不是其他方式。 – Eddy

+0

@Eddy謝謝你比我更明確地指出了這一點。 – Ingo

+0

這沒有意義。爲什麼第二個最內層的authors.id會工作呢?順便說一句,在PostgreSQL和SQL Server中,查詢工作得很好。 – sayap

0

這也失敗在MySQL中使用完全相同的錯誤:

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

我會懷疑查詢確實是不正確。我相信你需要參考最內層查詢中的FROM子句中的authors表。最近我一直在做很多NOSQL的工作,所以我的SQL查詢技能有點塵土飛揚,但我敢肯定,一個內部查詢無法達到其他表。

如果可以,請使用連接而不是嵌套查詢重寫查詢。無論如何,嵌套查詢的性能往往很差(在DB2中未經證實,但至少在MySQL 5.1中是這樣)。

+0

我真的很驚訝,查詢在MySQL中不起作用。僅供參考,它在PostgreSQL和SQL Server中運行良好。無論如何,關於「內部查詢無法聯繫到其他表」的部分肯定是錯誤的。查詢如'SELECT a.key,(SELECT count(*)FROM b WHERE b.key = a.key)AS count FROM a'在任何數據庫中工作正常。 – sayap

+0

當子查詢處於'FROM'子句中時它工作嗎? –