【发布时间】:2019-02-18 01:30:05
【问题描述】:
嗨,我遇到了一个 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
【问题讨论】:
-
样本数据和期望的结果真的很有帮助。
-
请提供一个minimal reproducible example,包括您的表的 DDL 语句(尤其是因为您有多种数据类型)和一些说明问题的示例数据以及您对该示例数据的预期输出。此外,请提供完整的查询,因为您只有一个 sn-p 并且
de别名似乎未定义,因此无法复制您的问题。 -
对不起,我添加了一个示例代码。
-
我已将代码替换为具有完全相同问题的示例代码,并给出相同的错误,它可在任何 oracle 数据库上运行。如果存在“双重”功能,也许还有其他人。
-
@EclecticFish 聚合函数,如
AVG不适用于VARCHAR数据类型,NUMBER或INTEGER在使用此类函数时是必须的。