[英]VARCHAR column with numeric and non-numeric data to be filtered by numeric comparasion in WHERE clause
DB:Oracle(但我正在尋找ANSI SQL中的通用解決方案)
SELECT *
FROM TABLE1 A INNER JOIN TABLE2 B ON A.FIELD_KEY = B.FIELD_KEY
WHERE TO_NUMBER (FIELD_VALUE) < 10
我有一個表(TABLE1)存儲'Value'和'Frequency'。 現在, FIELD_VALUE
列中的數據可以是數字也可以是非數字。 此列的數據類型為VARCHAR2
。 我想過濾這個值<10(比如說)的表。
我知道'Where TO_NUMBER(Value)<10'不起作用,因為Value列也包含非數字數據。
但是,我正在將表TABLE1
與表TABLE2
連接在一起這樣只在數值中返回數據值,在“值”列的結果集中返回,然后我在這個已經過濾的結果集中應用'Where TO_NUMBER(Value)<10'。 我期待由於結果集已經過濾並且僅包含“值”列中的數值數據,我應該能夠使用“Where TO_NUMBER(Value)<10”caluse進一步過濾結果集但是由於沒有發生事實上Oracle優化器更改了我的where子句和連接條件的順序,因此我得到'ORA-01722:無效數字'錯誤。
適合我的解決方案是:
WITH BASE_QUERY
AS (SELECT *
FROM TABLE1 A INNER JOIN TABLE2 B ON A.FIELD_KEY = B.FIELD_KEY)
SELECT *
FROM BASE_QUERY A
INNER JOIN
BASE_QUERY B
ON A.VALUE = B.VALUE AND TO_NUMBER (FIELD_VALUE) < 10
但我要在這里進行自我加入,這是昂貴且不必要的。 另外,我不確定這個解決方案是否會一直有效。 我的意思是,如果Oracle在加入表之前更改了執行計划並執行TO_NUMBER (FIELD_VALUE) < 10
,那么查詢可能會再次失敗並出現相同的“ORA-01722:無效數字”錯誤。
問題:
但我要在這里進行自我加入,這是昂貴且不必要的。
所以不要做聯接。 您只需FIELD_VALUE
作為DIGIT的行 。 您想忽略ALPHANUMERIC值。 因此,只過濾掉數字。
例如,
TRANSLATE和REPLACE
SQL> WITH DATA AS(
2 SELECT 'mix-'||LEVEL str FROM dual CONNECT BY LEVEL <=10
3 UNION ALL
4 SELECT to_char(LEVEL) FROM dual CONNECT BY LEVEL <=10
5 )
6 SELECT str FROM DATA
7 WHERE REPLACE(translate(str, '0123456789',' '), ' ') IS NULL
8 /
STR
--------------------------------------------
1
2
3
4
5
6
7
8
9
10
10 rows selected.
SQL>
REGEXP_LIKE
SQL> WITH DATA AS(
2 SELECT 'mix-'||LEVEL str FROM dual CONNECT BY LEVEL <=10
3 UNION ALL
4 SELECT to_char(LEVEL) FROM dual CONNECT BY LEVEL <=10
5 )
6 SELECT str FROM DATA
7 WHERE REGEXP_LIKE(str, '^[[:digit:]]+')
8 /
STR
--------------------------------------------
1
2
3
4
5
6
7
8
9
10
10 rows selected.
SQL>
就個人而言,我會選擇TRANSLATE和REPLACE,因為REGEXP仍然非常耗費資源。
如果您可以保證以數字開頭的field_value
中的內容將嚴格為數字,則可以使用過濾表的子查詢,只留下field_value
列中包含數字內容的記錄:
select *
from (
select t1.*
from table t1
where t1.field_value >= '0'
and t1.field_value <= chr(ascii('9')+1) -- ':'; invariant to charset and encoding
) t
where to_number(t.field_value) < 10
;
我寧願建議你使用Lalit Kumar B的解決方案之一,這個解決方案似乎更加強大(考慮放松未來的“從初始數字推斷數字”政策)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.