У меня есть таблица, содержащая 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, это, к сожалению, значительно ограничивает диапазон доступных функций.
Пожалуйста, не могли бы вы отредактировать свое сообщение, чтобы включить блоки кода, которые показывают два запрошенных SQL-запроса. Кроме того, возможно, стоит указать, какую СУБД вы используете. – w5m