Oracle查询:将表中的值与同一表中的其他值进行比较

时间:2015-06-24 12:40:35

标签: sql oracle

我们有一个基于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);

但是我必须为“module”的每个值运行查询。

我想做的是编写一个允许我一次性执行此操作的查询。有人暗示我可以使用游标语句,但我很难找到一个“oracle游标傻瓜”类型的文章,到目前为止,我所看到的并没有帮助我,包括http://docs.oracle.com/cd/B28359_01/server.111/b28286/expressions006.htm#SQLRF52057。有谁能提出建议?

感谢。

3 个答案:

答案 0 :(得分:0)

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

如果是这样,有几个好的配置(这就是db说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 :(得分:0)

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

localStorage

答案 2 :(得分:0)

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

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;