【问题标题】:Oracle query: compare values in table to other values in same tableOracle查询:将表中的值与同一表中的其他值进行比较
【发布时间】:2015-06-24 12:40:35
【问题描述】:

我们有一个基于 Oracle 的系统来管理设备并将其详细信息和配置存储在一个名为“configs”的表中。每个设备由几个模块组成,每个模块的配置保存为逗号分隔的字符串。例如:

device_id   module  values
1           1       3,4,2,3
1           2       4,1,3,4
1           3       2,1,2,3
1           4       6,4,2,1
1           5       1,4,2,3
1           6       1,3,4,4
2           1       3,4,2,3
2           2       4,1,3,4
2           3       2,3,2,3
2           4       6,4,2,1
2           5       1,8,2,3
2           6       1,3,4,4
3           1       3,4,2,3
3           2       4,1,3,4
3           3       2,1,2,3
3           4       6,4,2,1
3           5       1,4,2,3
3           6       1,3,4,4
4           1       3,4,2,3
4           2       4,1,3,4
4           3       2,1,2,4
4           4       6,4,2,1
4           5       1,4,2,3
4           6       1,3,7,4

我需要审核系统并识别其配置与已知良好配置不匹配的每个模块。理想情况下,我想运行这样的查询,假设设备 1 的配置是我的好配置:

select device_id,module 
from configs 
where values != (select values from configs where device_id = 1)

但这会返回错误:

ORA-01427: single-row subquery returns more than one row

如果我将查询更改为此,它可以工作:

 select device_id,module 
 from configs 
 where values = (select values from configs where device_id = 1 and module = 1);

但是我必须对“模块”的每个值运行查询。

我想做的是编写一个查询,让我可以一次性完成。有人暗示我可以使用游标语句,但我一直在努力寻找“用于傻瓜的 oracle 游标”类型的文章,到目前为止,我所看到的任何内容都没有帮助我,包括 http://docs.oracle.com/cd/B28359_01/server.111/b28286/expressions006.htm#SQLRF52057。任何人都可以提出一些建议吗?

谢谢。

【问题讨论】:

  • 您如何确定“已知良好的配置”是什么?
  • 基本上,所有的配置都应该是一样的,但随着时间的推移,事情已经被修改了。我们知道设备 1 的配置是所有其他设备的配置。

标签: sql oracle


【解决方案1】:

模块编号是否必须匹配?即模块 2(设备 1)的配置是否被认为是模块 3(其他设备)的良好配置

如果是这样,有几个很好的配置(这就是数据库显示single-row subquery returns more than one row 的原因)。你必须考虑到这一点:

select device_id, module 
from configs 
where values not in (select values from configs where device_id = 1)

如果没有,您必须选择与考虑的行匹配的行,例如:

select device_id, module
from configs c1
where values = ( 
    select values
    from configs c2 
    where device_id = 1 
    and c1.module = c2.module
)

【讨论】:

  • 设备1的整个配置(即所有模块)应该是所有其他设备的配置方式。
  • 所以,第二个查询可能更好,因为它将每个设备的每个模块与设备 1 的相同模块进行比较
  • 谢谢。您的两个建议都返回一组结果,但每一个都是不同的一组,所以我需要挑选它们以确定哪个是正确的。
【解决方案2】:

产生错误的查询正在尝试比较单值上下文中的项目列表。您需要将“!=”更改为“不在”,它应该可以工作。这是调整后的查询:

select device_id, module 
from configs 
where values not in (select values from configs where device_id = 1)

【讨论】:

    【解决方案3】:

    如果我理解正确,我想你可以使用这样的东西:

    DECLARE
        device_string VARCHAR2 (100);
    BEGIN
        FOR i IN (SELECT * FROM configs WHERE device_id = 1)
        LOOP
            SELECT listagg(device_id, ';')
            WITHIN GROUP (ORDER BY device_id)
            INTO device_string
            FROM configs
            WHERE values != i.values AND module=i.module;
    
            DBMS_OUTPUT.PUT_LINE(
                ' Bad config for module ' || i.module ||
                ' in devices: ' || device_string);
        END LOOP;
    END;
    

    【讨论】:

    • 原谅我的愚蠢,但是当我最后按回车时这不会执行,我只是得到另一个提示。我尝试将它放入一个文本文件并使用 @ 执行它,但得到相同的结果。
    • >" 我刚刚得到另一个提示" 你在使用 sqlplus 吗?如果是这样,我认为您需要在DECALRE 语句之前添加SET SERVEROUTPUT ON;,在最后一个END; 之后添加斜杠'/'
    猜你喜欢
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 2020-07-30
    • 2021-02-22
    • 1970-01-01
    相关资源
    最近更新 更多