2015-09-16 278 views
0

假設,我們有這樣的查詢:ORA-00904:在嵌套子查詢中無效的標識符

SELECT 
tt.id first_column, 
tt.value second_column, 
--another values 
qq.code_1 third_column, 
qq.code_2 column4, 
qq.code_3 column5, 
qq.code_4 column6, 
qq.code_5 column7 

FROM 
test_tbl tt LEFT JOIN 
(SELECT * FROM (
    SELECT id, code_value, ROW_NUMBER() OVER (ORDER BY code_value) AS RN 
    FROM attributes attr WHERE attr.id = tt.id AND 
     attr.code IN ('ATTRIBUTE_CODE_1', 
        'ATTRIBUTE_CODE_2', 
        'ATTRIBUTE_CODE_3', 
        'ATTRIBUTE_CODE_4', 
        'ATTRIBUTE_CODE_5') 
) 
PIVOT (MAX(code_value) FOR (RN) IN (1 as code_1, 2 as code_2, 3 as code_3, 4 as code_4, 5 as code_5))) qq 
ON tt.id = qq.id 
-- LEFT JOINS with another tables... 

的問題是錯誤:

ORA-00904: "TT"."ID": invalid identifier 

我怎樣才能繞過這個障礙?

當然上面的例子很容易和虛擬,真正的查詢比較複雜。

這個例子可以在這裏檢查:http://sqlfiddle.com/#!4/eec83/3

回答

1

只需刪除有問題的條件:

WHERE attr.id = tt.id 

...但是,以確保正確RN值,您還需要添加一個partition by idrow_number() over子句中。

ROW_NUMBER() OVER (PARTITION BY id ORDER BY code_value) AS RN 

SQLFiddle Demo

SELECT 
tt.id first_column, 
tt.value second_column, 
--another values 
qq.code_1 third_column, 
qq.code_2 column4, 
qq.code_3 column5, 
qq.code_4 column6, 
qq.code_5 column7 

FROM 
test_tbl tt LEFT JOIN 
(SELECT * FROM (
    SELECT id, code_value, ROW_NUMBER() OVER (partition by id ORDER BY code_value) AS RN 
    FROM attributes attr WHERE 
     attr.code IN ('ATTRIBUTE_CODE_1', 
        'ATTRIBUTE_CODE_2', 
        'ATTRIBUTE_CODE_3', 
        'ATTRIBUTE_CODE_4', 
        'ATTRIBUTE_CODE_5') 
) 
PIVOT (MAX(code_value) FOR (RN) IN (1 as code_1, 2 as code_2, 3 as code_3, 4 as code_4, 5 as code_5))) qq 
ON tt.id = qq.id 
0

您可以從內部子查詢中刪除這一條件,因爲它不因爲你已經左外連接這兩個表上的公共列id任何意義。

您可以對查詢進行以下更改。

SELECT 
tt.id first_column, 
tt.value second_column, 
qq.code_1 third_column, 
qq.code_2 column4, 
qq.code_3 column5, 
qq.code_4 column6, 
qq.code_5 column7 
FROM 
test_tbl tt LEFT JOIN 
(SELECT * FROM (
    SELECT id, code_value, ROW_NUMBER() OVER (ORDER BY code_value) AS RN 
    FROM attributes attr WHERE 
    attr.code IN ('ATTRIBUTE_CODE_1', 
       'ATTRIBUTE_CODE_2', 
       'ATTRIBUTE_CODE_3', 
       'ATTRIBUTE_CODE_4', 
       'ATTRIBUTE_CODE_5') 
) 
PIVOT (MAX(code_value) FOR (RN) 
IN (1 as code_1, 2 as code_2, 3 as code_3, 4 as code_4, 5 as code_5))) qq 
ON tt.id = qq.id; 

這裏是你的Updated SQL Fiddle

也許這會幫助你。

+0

不幸的是,這不是有效的其他數據。看看這個:http://sqlfiddle.com/#!4/ac236d/2 –

+0

你可以請示例輸出? –

1

您不能引用的內嵌視圖其他表/視圖。我找不到說明這一點的文檔,但僅此而已。在設計上,查詢優化器如何處理查詢。

實際情況是這個簡單的查詢更加明顯:

SELECT 
    * 
FROM 
    test_tbl tt , 
    ( 
    SELECT ID, CODE_VALUE 
    FROM attributes attr 
    WHERE attr.id = tt.id 
    ) qq 

錯誤:

ORA-00904: "TT"."ID": invalid identifier 

如果你想要做的加入,那麼你應該使用JOIN,把條件開條款或將條件放在WHERE子句中以加入內聯視圖和表格。 喜歡這裏:

SELECT 
    * 
FROM 
    test_tbl tt , 
    ( 
    SELECT ID, CODE_VALUE 
    FROM attributes attr 
    ) qq 
WHERE attr.id = tt.id 

還是看你是否想使CROSS APPLY。看起來這是一個加入。

也看到這個answer,有一個很好的表達:

An inline view/derived table creates a temporary unnamed view at the beginning of your query and then treats it like another table until the operation is complete. Because the compiler needs to create a temporary view when it sees on of these subqueries on the FROM line, those subqueries must be entirely self-contained with no references outside the subquery.

我相信這並非總是如此,在某些情況下,Oracle可以選擇合併內嵌視圖。並可以通過使用NO_MERGE優化器提示強制合併。

SEE THIS

SEE THIS

我打算儘快我可以添加查詢計劃,這可能會給更多的想法