1. 程式人生 > >[oracle] count()函式使用錯誤欄位導致的查詢失敗(聚合函式聚合欄位與分組欄位不一致)

[oracle] count()函式使用錯誤欄位導致的查詢失敗(聚合函式聚合欄位與分組欄位不一致)

一 錯誤的SQL語句(原始的,格式是直接從word中拷貝的,存在多個錯誤):

select to_char(t.fbsj, 'YYYY') as a, count(t.fbsj) from (

select fbsj from ods_t_ky_lw

    where

      to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

        and

        to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by a ;

 附:建表語句及資料

連結: https://pan.baidu.com/s/1Qhv0ajPtefdqXd2P2LVXdw 提取碼: q4bb 

二 除錯過程

1 調整一(可執行的):

1.1 取出來子sql直接執行,發現不行,報錯ora-00911:invalid character

1.2 使用的是navicat這個工具,按說關鍵字是應該有顏色提示的,除非關鍵字沒有被正確是被正確識別到,想到可能是因為sql中間有些oracle不認可的不可見字元,可以把所有空白符都刪掉,自行處理分隔,如下即ok(如果直接拷貝使用,可能放到navicat裡面還是要重新編輯一下):

select fbsj from ods_t_ky_lw where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7

2 調整二(不可執行)

直接加上外層sql,無法執行,說明外層sql還是有問題,SQL及報錯如下:

select to_char(t.fbsj, 'YYYY') as a, count(t.fbsj) from (

select fbsj from ods_t_ky_lw where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by a ;

報錯:ORA-00904:“A”:invalid identifier

3 調整三(不可執行)

3.1 從上一個報錯結合字型顏色,會誤以為A是個oracle關鍵字,那就換一個試試(比如fb),實際上還是不行,報錯類似,只不過提示的字元變了:ORA-00904:“FB”:invalid identifier

3.2 看SQL中,欄位名稱有時用小寫,有時用大寫,是不是因為大小寫混用導致?oracle中大小寫混用時,需要對欄位加上雙引號,實際結果還是不行(其實分析到這裡是陷入歧途了,因為如果因為大小寫混用導致錯誤,第一次調整中就有大小寫混用沒報錯,因此不應該是大小寫混用的問題),SQL及報錯如下:

select to_char(t.fbsj, 'YYYY') as fb, count(t.fbsj) from (

select fbsj from ods_t_ky_lw where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by fb ;

報錯:ORA-00904:“fbsj”:invalid identifier

3.3 然後又去掉對fbsj欄位的雙引號,對fb加雙引號,也還是不行,報錯跟上面差不多,只不過是換成fb是無效識別符號,ORA-00904:“fb”:invalid identifier。

3.4 然後對fb加單引號,報錯如下:

select to_char(t.fbsj, 'YYYY') as fb, count(t.fbsj) from (

select fbsj from ods_t_ky_lw where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by fb ;

報錯:ORA-00923:from keywords not found where expected

原因:查詢網上資料,有一篇文章提到oracle的列別名不能用單引號也不能用數字。

整個“調整三”的分析基本沒有作用,不過3.2的結果可以保留,就是將別名a替換成fb,在不確定a是否關鍵字的情況下,換一個肯定不是關鍵字的,確保後面的如果有正確的嘗試,不會因此受影響。

4 調整(最終是想要的結果的):

分析又回到了原點,分析一下語義(格式什麼的已經沒有其他可嘗試的了)會發現:fbsj是一個date型別的資料,oracle中date型別的資料至少會是年月日(不做格式轉換的話,就是年月日時分秒),不可能只是四位的年份,而查詢語句中需要將查詢出來的fbsj只取年份做聚合,然後在查詢語句中顯示年份和年月日時分秒的統計結果?!該怎麼統計呢?按照年份分組,然後統計的是fbsj這一秒多少條資料/是下一秒的又有多少條,你讓oracle怎麼給你展示?分組欄位和分組聚合函式使用的欄位不一致!!明確了原因了之後接下來又有兩種修改方向:

4.1 既然是count裡面的欄位不對,直接將其改掉的了:

4.1.1 修改一sql:

select to_char(t.fbsj, 'YYYY') as fb, count(fb) from (

select fbsj from ods_t_ky_lw where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by fb ;

報錯:ORA-00904:“FB”:invalid identifier

原因:fb是在最外層select中定義的,count也是在這一層,oracle怎麼邊計算著fb,count就直接拿來用了,要是沒計算完怎麼辦?所以不能在同一層或更內層使用別名。

4.1.2 修改二sql:

select to_char(t.fbsj, 'YYYY') as fb, count(to_char(t.fbsj, 'YYYY')) from (

select fbsj from ods_t_ky_lw where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by fb ;

報錯:ORA-00904:“FB”:invalid identifier

原因:其實按照計算來說這麼做應該沒什麼錯誤,但是oracle的sql語法直譯器可能還是會認為count裡面的東西跟group by後的內容不一致導致報錯。

4.1.3 修改三sql:

select to_char(t.fbsj, 'YYYY') as fb, count(to_char(t.fbsj, 'YYYY') as fb) from (

select fbsj from ods_t_ky_lw where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by fb ;

報錯:ORA-00907:missing right paranthesis

原因:oracle中的內建函式裡面的引數,如果前後多空格或無空格都不影響執行,只要引數個數對(用英文逗號分隔)就行,所以不用考慮空格的事情,不是因為前後空格導致誤判右括號缺失。

其實oracle中很多“ORA-00907:missing right paranthesis”右括號缺失是因為其他問題導致的誤判(除非真正發現括號數量不成對),這種情況一般都是因為sql中存在語法上的不完整或順序顛倒(可參考https://blog.csdn.net/gggwfn1982/article/details/81627827)。

4.2 還是根據語義來修改,實際上外層只會使用到FBSJ欄位的年份,因此對這個欄位的處理可以放在內層select語句中,如下即可:

select fb, count(fb) from (

select to_char(fbsj, 'YYYY') as fb from ods_t_ky_lw

where

to_char(FBSJ, 'YYYY') <= to_char(sysdate, 'YYYY')

and

to_char(FBSJ, 'YYYY') >= to_char(sysdate, 'YYYY') - 7) t

group by fb ;