2013-07-31 8 views
1

У меня есть таблица, содержащая 5 столбцов. Первый столбец содержит идентификатор, два столбца содержат параметры для этих идентификаторов со значениями 0 или 1, третий столбец содержит параметр, который мне нужен для вывода, последний столбец содержит дату. Же идентификатор может появиться в нескольких рядах с различными параметрами:SQL: выбор уникальных значений на основе условий

ID  parameter1  parameter2  parameter3  date 

001  0    1     A    01.01.2010 
001  0    1     B    02.01.2010 
001  1    0     C    01.01.2010 
001  1    1     D    01.01.2010 
002  0    1     A    01.01.2010 

Для каждого уникального идентификатора Я хочу, чтобы вернуть значение в parameter3, решение, из какой строки для возврата этого значения на основе значений в parameter1 и parameter2 и дата:

  • Если есть строка с обоими параметрами: 0, я хочу значение в этой строке.
  • Если нет такой строки, я хочу значение из строки, где параметр1 является 0 и параметр2 является 1,
  • Если нет такой строки, я хочу, чтобы строка, где параметр1 является 1 и параметр2 является 0.
  • Наконец, если такой строки нет, мне нужно значение из строки с обоими параметрами: 1.

Если существует несколько строк, соответствующих требуемым условиям, я хочу, чтобы строка имела самую последнюю дату.

например, для таблицы выше, для ID 001 Мне нужна вторая строка со значением B в параметре3.

Что было бы самым эффективным/быстрым способом для этого? Я попробовал два подхода до сих пор:

Первый из них состоял в том, чтобы выбрать все отдельные идентификаторы, а затем пронумеровать отдельные идентификаторы, используя оператор select с идентификатором в документе where, а затем прокрутить все строки, соответствующие ID, в то время как хранить необходимые значения в переменных .:

foreach 
    select distinct ID into i_ID from table1 
     foreach 
      let o_case = 5 
      select case 
       when parameter1 = 0 and parameter2 = 0 then 1 
       when parameter1 = 0 and parameter2 = 1 then 2 
       when parameter1 = 1 and parameter2 = 0 then 3 
       when parameter1 = 1 and parameter2 = 1 then 4 
       end, parameter3, date 
       into i_case, i_p3, i_date 
       from table3 
       where table3.ID = i_ID 

       if i_case < o_case 
        then let o_p3, o_case, o_date = i_p3, i_case, i_date; 
        else (if i_case = o_case and i_date > o_date 
         then let o_p3, o_date = i_p3, i_date; 
        end if; 
       end if; 
     end foreach; 
     insert into table_output values(i_ID; o_p3); 
end foreach; 

Второй подход к левой присоединиться к столу в четыре раза с собой на ID и применять различные комбинации параметр1 & параметр2, как описано выше в левой присоединяется, то выбор выхода через гнездовые nvl статьи:

select ID, 
    nvl(t1.parameter3, 
     nvl(t2.parameter3, 
      nvl(t3.parameter3, 
       nvl(t4.parameter3)))) parameter3 
from table1 t0 
    left join table1 t1 
     on t0.ID = t1.ID and t1.parameter1 = 0 and t1.parameter2 = 0 
     and t1.date = (select max(date) from table1 t1a where t1a.ID = t1.ID)   
    left join table1 t2 
     on t0.ID = t2.ID and t2.parameter1 = 0 and t2.parameter2 = 1 
     and t2.date = (select max(date) from table1 t2a where t2a.ID = t1.ID) 
    left join table1 t3 
     on t0.ID = t3.ID and t3.parameter1 = 1 and t3.parameter2 = 0 
     and t3.date = (select max(date) from table1 t3a where t3a.ID = t3.ID) 
    left join table1 t4 
     on t0.ID = t4.ID and t4.parameter1 = 1 and t4.parameter2 = 1 
     and t4.date = (select max(date) from table1 t4a where t4a.ID = t4.ID) 

Оба подхода в основном работали, однако, поскольку таблица действительно длинная, они были слишком медленными. Чтобы вы посоветовали?

PS: СУБД - это IBM Informix 10, это, к сожалению, значительно ограничивает диапазон доступных функций.

+1

Пожалуйста, не могли бы вы отредактировать свое сообщение, чтобы включить блоки кода, которые показывают два запрошенных SQL-запроса. Кроме того, возможно, стоит указать, какую СУБД вы используете. – w5m

ответ

1

Я не уверен, если это то, что вы хотите, но это может работать:

SELECT id, parameter3 
FROM (
    SELECT id, parameter3, RANK() OVER (
      PARTITION BY id, parameter3 
      ORDER BY parameter1 ASC, parameter2 ASC, date DESC 
     ) 
    FROM tab 
) AS x 
WHERE x.rank = 1; 
+0

Забыл упомянуть, что я застрял в IBM Informix 10. Ранг не работает там, а также подзапросы в разделе –

+0

@MaxK жаль слышать это .. Тогда я не могу вам помочь. –

0
ID  parameter1  parameter2  parameter3  date 

001  0    1     A    01.01.2010 
001  0    1     B    02.01.2010 

оба указанных выше строк, имеющих одинаковый идентификатор, paramaeter1, параметр2, но разные paraameter3, он может создать проблема для вас.

+0

Я включил это специально для демонстрации характеристик таблицы. Могут быть случаи, когда один и тот же идентификатор с одинаковыми значениями в параметрах 0 и 1 существует в нескольких строках. Однако в этом случае дата будет отличаться –

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