Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
448 views
in Technique[技术] by (71.8m points)

sql - ORACLE - Select Count on a Subquery

I've got an Oracle table that holds a set of ranges (RangeA and RangeB). These columns are varchar as they can hold both numeric and alphanumeric values, like the following example:

ID|RangeA|RangeB
1 |   10 |   20
2 |   21 |   30
3 | AB50 | AB70
4 | AB80 | AB90

I need to to do a query that returns only the records that have numeric values, and perform a Count on that query. So far I've tried doing this with two different queries without any luck:

Query 1:

SELECT COUNT(*) FROM (
SELECT RangeA, RangeB FROM table R
WHERE upper(R.RangeA) = lower(R.RangeA)
) A
WHERE TO_NUMBER(A.RangeA) <= 10

Query 2:

WITH A(RangeA,RangeB) AS(
SELECT RangeA, RangeB FROM table 
WHERE upper(RangeA) = lower(RangeA)
)
SELECT COUNT(*) FROM A WHERE TO_NUMBER(A.RangeA) <= 10

The subquery is working fine as I'm getting the two records that have only numeric values, but the COUNT part of the query is failing. I should be getting only 1 on the count, but instead I'm getting the following error:

ORA-01722: invalid number
01722. 00000 -  "invalid number"

What am I doing wrong? Any help is much appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can test each column with a regular expression to determine if it is a valid number:

SELECT COUNT(1)
FROM   table_of_ranges
WHERE  CASE WHEN REGEXP_LIKE( RangeA, '^-?d+(.d*)?$' )
            THEN TO_NUMBER( RangeA )
            ELSE NULL END
          < 10
AND    REGEXP_LIKE( RangeB, '^-?d+(.d*)?$' );

Another alternative is to use a user-defined function:

CREATE OR REPLACE FUNCTION test_Number (
  str VARCHAR2
) RETURN NUMBER DETERMINISTIC
AS
  invalid_number EXCEPTION;
  PRAGMA EXCEPTION_INIT(invalid_number, -6502);
BEGIN
  RETURN TO_NUMBER( str );
EXCEPTION
  WHEN invalid_number THEN
    RETURN NULL;
END test_Number;
/

Then you can do:

SELECT COUNT(*)
FROM   table_of_ranges
WHERE  test_number( RangeA ) <= 10
AND    test_number( RangeB ) IS NOT NULL;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...