Oracle SQL Case中的数字无效

时间:2018-09-13 10:15:05

标签: sql oracle case

嗨,我遇到了SQL案例的麻烦,问题是我试图用7个不同的列运行案例,这些列根据ID可以具有不同种类的数据(字符串,日期,数字)。

这意味着在某些ID下,一列中的行将是字符串,而在其他ID下,一列中的行将是数字。

我意识到这不是结构化数据库的常规用法,但是此特定表用于特定目的,过去该方法被认为是有用的。

该情况仅在该列确实具有数字时才选择“ then”。但是,当我运行它时,我得到一个无效的号码ORA-01722。因为其中之一行将包含字符串og日期。

我正确地意识到了这一点,因为oracle在执行之前先对sql进行了评估,并且没有顺序执行,因此即使实际上不必在给定ID下对列进行计算,也会在这些列上产生错误。

我试图执行的代码如下,'then'之前的硬编码1和2将根据ctrl_id(唯一ID)而变化,这将是我们只看一眼的安全代码和一个list_val列/行,一个数字

WITH sampledata1 AS
 (SELECT '1' ctrl_id, '23' list_val1, 'Textfield' list_val2
    FROM dual),
sampledata2 AS
 (SELECT '2' ctrl_id, 'Textfield' list_val1, '45' list_val2
    FROM dual),
sampledata3 AS
 (SELECT *
    FROM sampledata1
  UNION
  SELECT *
    FROM sampledata2)
SELECT CASE
          WHEN ctrl_id = 1 THEN
           AVG(list_val1)
           over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
          WHEN ctrl_id = 2 THEN
           AVG(list_val2)
           over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
        END AS avg_val
  FROM sampledata3 qd

关于如何进行这项工作的任何建议。解决方法还是其他方法?

提前谢谢。

---------下面的解决方案

我使用了下面发布的一些建议和解决方案,并使此代码有效。我将尝试在系统中实现它。感谢您为大家节省的很多麻烦。

 WITH sampledata1
     AS (SELECT '1' ctrl_id, '23' list_val1, 'Textfield' list_val2 FROM DUAL),
     sampledata2
     AS (SELECT '2' ctrl_id, 'Textfield' list_val1, '45' list_val2 FROM DUAL),
     sampledata3
     AS (SELECT * FROM sampledata1
         UNION
         SELECT * FROM sampledata2)
 select ctrl_id,
 avg(CASE WHEN TRIM(TRANSLATE(list_val1, ' +-.0123456789', ' ')) is null 
 then list_val1 else null end) over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC) list_val1,
    avg(CASE WHEN TRIM(TRANSLATE(list_val2, ' +-.0123456789', ' ')) is null 
 then list_val2 else null end) over(PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC) list_val2
       
            from   sampledata3 qd

2 个答案:

答案 0 :(得分:1)

类似于eq(variables['task.A.status'], 'failure')的{​​{3}}不适用于AVG数据类型,使用此类功能时必须使用VARCHARNUMBER

我将查询修改为使用数字而不是字符串

INTEGER

输出为

WITH sampledata1
     AS (SELECT '1' ctrl_id, '23' list_val1, '43' list_val2 FROM DUAL),
     sampledata2
     AS (SELECT '2' ctrl_id, '34' list_val1, '45' list_val2 FROM DUAL),
     sampledata3
     AS (SELECT * FROM sampledata1
         UNION
         SELECT * FROM sampledata2)
SELECT CASE
          WHEN ctrl_id = 1
          THEN
             AVG (list_val1)
                OVER (PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
          WHEN ctrl_id = 2
          THEN
             AVG (list_val2)
                OVER (PARTITION BY qd.ctrl_id ORDER BY qd.ctrl_id ASC)
       END
          AS avg_val
  FROM sampledata3 qd

编辑1

也许您可以执行以下操作来首先确定行返回NUMERIC或NON-NUMERIC。

根据您的要求进行更改。

  AVG_VAL
----------
        23
        45

答案 1 :(得分:1)

您可以尝试使用

之类的非数字符号过滤掉值
AVG(CASE WHEN TRIM(TRANSLATE(list_val1, ' +-.0123456789', ' ')) is null then list_val1 else null end) OVER (...)

NB!不幸的是,诸如“ + 12-.3”之类的字符串也将被识别为数字,在这种情况下,您将获得相同的ora-01722