Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql ORACLE-选择子查询上的计数_Sql_Oracle_Count_Subquery - Fatal编程技术网

Sql ORACLE-选择子查询上的计数

Sql ORACLE-选择子查询上的计数,sql,oracle,count,subquery,Sql,Oracle,Count,Subquery,我有一个Oracle表,其中包含一组范围(RangeA和RangeB)。这些列是varchar,因为它们可以同时保存数字和字母数字值,如以下示例所示: ID|RangeA|RangeB 1 | 10 | 20 2 | 21 | 30 3 | AB50 | AB70 4 | AB80 | AB90 我需要执行一个只返回具有数值的记录的查询,并对该查询执行计数。到目前为止,我已经尝试使用两个不同的查询来执行此操作,但没有任何运气: 问题1: SELECT COUNT(*) FROM

我有一个Oracle表,其中包含一组范围(RangeA和RangeB)。这些列是varchar,因为它们可以同时保存数字和字母数字值,如以下示例所示:

ID|RangeA|RangeB
1 |   10 |   20
2 |   21 |   30
3 | AB50 | AB70
4 | AB80 | AB90
我需要执行一个只返回具有数值的记录的查询,并对该查询执行计数。到目前为止,我已经尝试使用两个不同的查询来执行此操作,但没有任何运气:

问题1:

SELECT COUNT(*) FROM (
SELECT RangeA, RangeB FROM table R
WHERE upper(R.RangeA) = lower(R.RangeA)
) A
WHERE TO_NUMBER(A.RangeA) <= 10
我做错了什么?非常感谢您的帮助。

请尝试以下查询:

  SELECT COUNT(*)
  FROM table R
  WHERE translate(R.RangeA, 'x0123456789', 'x') = 'x' and
        translate(R.RangeB, 'x0123456789', 'x') = 'x'
首先,您不需要为此目的使用子查询。其次,使用
到_number()
upper()
/
lower()
容易出现其他问题。函数
translate()
将第二个参数中的每个字符替换为第三个参数中的值。在这种情况下,它会删除数字。如果没有剩余值,则原始值为整数


您可以对负值和浮点数进行更复杂的检查,但问题中的示例似乎是关于正整数值。

您可以使用正则表达式测试每一列,以确定它是否为有效数字:

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*)?$' );
然后你可以做:

SELECT COUNT(*)
FROM   table_of_ranges
WHERE  test_number( RangeA ) <= 10
AND    test_number( RangeB ) IS NOT NULL;
选择计数(*)
从_范围的表_

其中test_number(RangeA)在大约四年后出现在这个问题上(显然,这里是从一个更新的线程指出的)。其他答案显示了如何实现所需的输出,但没有回答OP的问题,即“我做错了什么?

你没有做错什么。甲骨文做错了什么。它将谓词(
WHERE
条件)从外部查询“推”到内部查询。推送谓词是优化器提高查询效率的最基本方法之一,但在某些情况下(您提出的问题就是一个完美的例子),结果实际上在逻辑上并不等同于原始查询


有一些方法可以防止优化器推送谓词;或者您可以用更好的方式编写查询(如其他答案所示)。但是,如果您想知道为什么会看到您看到的内容,这就是原因。

Oracle将空字符串表示为
NULL
,并将其传递给
TRANSLATE()
,然后对任何输入字符串返回
NULL
。您必须执行以下操作:
RangeA不为NULL,而REPLACE(TRANSLATE(RangeA,'0123456789','0000000000'),'0','')为NULL
@MT0-获得正确结果的更好方法是(不使用
REPLACE
):
TRANSLATE(RangeA,'z0123456789','z')为NULL
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*)?$' );
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;
/
SELECT COUNT(*)
FROM   table_of_ranges
WHERE  test_number( RangeA ) <= 10
AND    test_number( RangeB ) IS NOT NULL;