2015-04-09 4 views
1

У меня есть таблица, как этотSQL: Выберите минимальное значение из нескольких столбцов с нулевыми значениями

ID Col1 Col2 Col3 
-- ---- ---- ---- 
1  7 NULL 12 
2  2  46 NULL 
3  NULL NULL NULL 
4  245  1 792 

Я хотел запрос, который дает следующий результат

ID Col1 Col2 Col3 MIN 
-- ---- ---- ---- --- 
    1  7 NULL 12 7 
    2  2  46 NULL 2 
    3 NULL NULL NULL NULL 
    4 245 1  792 1 

Я имею в виду, я хотел столбец, содержащий минимальные значения из Col1, Col2 и Col3 для каждой строки, игнорируя значения NULL. В предыдущем вопросе (What's the best way to select the minimum value from multiple columns?) есть ответ для значений, отличных от NULL. Мне нужен максимально эффективный запрос для огромной таблицы.

Select Id, 
     Case When Col1 < Col2 And Col1 < Col3 Then Col1 
      When Col2 < Col1 And Col2 < Col3 Then Col2 
      Else Col3 
      End As MIN 
From YourTableNameHere 
+0

Какой базу данных вы используете? Вы должны соответствующим образом пометить свои вопросы. –

ответ

0

Это может работать:

Select id, Col1, Col2, Col3, least(Col1, Col2, Col3) as MIN From YourTableNameHere 
+0

LEAST не реализован во всех базах данных. Я знаю, что это в Oracle и MySQL, но не в SQL Server. –

3

Предполагая, что вы можете определить некоторые "максимальное" значение (я буду использовать 9999 здесь), что ваши реальные ценности никогда не будет превышать:

Select Id, 
     Case When Col1 < COALESCE(Col2, 9999) 
      And Col1 < COALESCE(Col3, 9999) Then Col1 
      When Col2 < COALESCE(Col1, 9999) 
      And Col2 < COALESCE(Col3, 9999) Then Col2 
      Else Col3 
     End As MIN 
    From YourTableNameHere; 
0

Вы не указали, какую версию Teradata вы используете. Если вы используете версию 14+, вы можете использовать least.

К сожалению, least вернет null, если любой из его аргументов равен NULL. Из документов:

LEAST поддерживает 1-10 цифровых значений. Если numeric_value является типом данных первого аргумента, тип данных возврата является числовым. Остальные аргументы в списке входных данных должны быть быть одинаковыми или совместимыми типами. Если входной параметр равен NULL, возвращается NULL.

Но вы можете обойти это, используя coalesce, как Джо сделал в своем ответе.

select id, 
    least(coalesce(col1,9999),coalesce(col2,9999),coalesce(col3,9999)) 
from mytable 
0

таким образом, вам не нужно, чтобы проверить nulls, просто использовать min и subquery

select tbl.id,tbl.col1,tbl.col2,tbl.col3, 
     (select min(t.col) 
     from ( 
      select col1 as col from tbl_name t where t.id=tbl.id 
      union all 
      select col2 as col from tbl_name t where t.id=tbl.id 
      union all 
      select col3 as col from tbl_name t where t.id=tbl.id 
      )t) 
from tbl_name tbl 

Выход:

1 7  NULL 12  7 
2 2  46  NULL 2 
3 NULL NULL NULL NULL 
4 245  1  792  1 
+0

Я подозреваю, что эти коррелированные подзапросы не будут хорошо работать для «огромной таблицы», указанной ОП. –

+0

Да, честно говоря, я пишу решение с использованием coalesce и case case, но вы отправили сообщение передо мной, поэтому я решил сказать по-другому – jfun

0

Просто измените запрос с coalesce() :

Select Id, 
     (Case When Col1 <= coalesce(Col2, col3, col1) And 
        Col1 <= coalesce(Col3, col2, col1) 
      Then Col1 
      When Col2 <= coalesce(Col1, col3, col2) And 
       Col2 <= coalesce(Col3, col1, col2) 
      Then Col2 
      Else Col3 
     End) As MIN 
From YourTableNameHere; 

Это не требует изобретать «магическое» число или чрезмерно усложнять логику.

0

Я нашел это решение более эффективным, чем использование нескольких предложений case case, которые могут быть чрезвычайно длинными при оценке данных из нескольких столбцов в одной строке.

Кроме того, я не могу взять кредит на это решение, поскольку нашел его на каком-то веб-сайте около года назад. Сегодня мне нужно было освежить эту логику, и я не мог найти ее нигде. Я нашел свой старый код и решил поделиться им на этом форуме.

Создание тестовой таблицы:

create table #testTable(ID int, Col1 int, Col2 int, Col3 int) 
Insert into #testTable values(1,7,null,12) 
Insert into #testTable values(2,2,46,null) 
Insert into #testTable values(3,null,null,null) 
Insert into #testTable values(4,245,1,792) 

Поиск минимального значения в данной строке:

Select ID, Col1, Col2, Col3 ,(SELECT Min(v) FROM ( VALUES (Col1), (Col2), (Col3) ) AS value(v)) [MIN] from #testTable order by ID 
Смежные вопросы