2015-06-24 3 views
0

У нас есть система на базе Oracle, которая управляет устройствами и сохраняет их данные и конфигурацию в таблице, называемой «configs». Каждое устройство состоит из нескольких модулей, и конфигурация каждого модуля сохраняется как строка, разделенная запятыми. Например:Запрос Oracle: сравнение значений в таблице с другими значениями в одной таблице

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); 

Но тогда я должен выполнить запрос для каждого значения «модуля».

Что бы я хотел сделать, это написать запрос, который позволит мне сделать это за один раз. Было намечено, что я могу использовать оператор курсора, но я изо всех сил пытался найти статью типа «оракулы для манекенов», и ничего, на что я смотрел, помог мне до сих пор, включая http://docs.oracle.com/cd/B28359_01/server.111/b28286/expressions006.htm#SQLRF52057. Может кто-нибудь что-то предложить?

Спасибо.

+0

, как вы определяете, что «известный хороший конфиг» есть? – OldProgrammer

+0

В принципе, все конфиги должны быть одинаковыми, но со временем все было переделано. Мы знаем, что конфигурация устройства 1 - это то, что должны быть все остальные. – Darren

ответ

0

Должны ли номера модулей соответствовать? то есть конфигурация модуля 2 (устройства 1), считающегося хорошей конфигурацией для модуля 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 
) 
+0

Вся конфигурация устройства 1 (то есть все модули) должна состоять в том, как настроены все остальные устройства. – Darren

+0

Итак, второй запрос, вероятно, лучше, поскольку он сравнивает каждый модуль каждого устройства с тем же модулем устройства 1 – bwt

+0

Спасибо. Оба предложения возвращают набор результатов, но каждый из них - другой набор, поэтому мне нужно выбрать их, чтобы определить, какой из них правильный. – Darren

0

Ваш запрос, который производит ошибки пытающегося сравнить список элементов в контексте одного значения. Вам нужно изменить свой «! =» На «не в», и он должен работать. Вот скорректированный запрос:

select device_id, module 
from configs 
where values not in (select values from configs where device_id = 1) 
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; 
+0

Простите мою глупость, но это не выполняется, когда я нажимаю Enter в конце, я просто получаю еще одно приглашение. Я попытался поместить его в текстовый файл и выполнить его с помощью @, но получить то же самое. – Darren

+0

> «Я просто получаю еще одно приглашение» Вы используете ** sqlplus **? Если это так, я думаю, вам нужно добавить 'SET SERVEROUTPUT ON;' перед оператором 'DECALRE' и после последнего' END; 'add slash '/' – um0f16

Смежные вопросы