Выберите строку из группы, которая удовлетворяет условию A. Если нет, дайте мне строку, которая удовлетворяет условию B

#sql #oracle

#sql #Oracle

Вопрос:

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

 Col1 |  Col2    | Col3 | Col4
100  | "Val1"   | 0    | 100
100  | "Val2"   | 1    | null
100  | "Val 3"  | 0    | null
101  |  "Val4"  | 0    | null
101  |  "Val5"  | 1    | null
102  |  "Val6"  | 0    | null
 

Мне нужна та единственная строка , где Col4!=null . Если все строки’ Col4 null , то верните мне строку where Col3=1 , но если оба Col4 null и Col3=0 , то верните мне любую одну строку.

Таким образом, результирующий набор для приведенных выше данных будет выглядеть следующим образом,

 Col1  |  Col2    |  Col3  | Col4
100   |  "Val1"  |   0    |  100
101   |  "Val5"  |   1    | null
102   |  "Val6"  |   0    | null
 

Я знаю, что это можно было бы сделать с помощью функции analytics, упорядочить их по Col1 Col4 Col3 и использовать аналитическую функцию для получения первой строки в каждой группе, но мы используем наш собственный ORM, который не поддерживает аналитическую функцию.

Пожалуйста, дайте мне знать, можно ли это сделать с помощью простого SQL (JOIN, Case и т. Д.).


Редактировать:

Будет только одна строка на группу, где Col4 имеет ненулевое значение, и одна строка на группу, где col3 есть 1 . Кроме того, одна строка в группе может удовлетворять обоим условиям Col4 отсутствия null и Col3=1 .

Комментарии:

1. Похоже, вы не упомянули, что хотите, чтобы Col1 был ключом разделения. В противном случае приведенный выше набор вернул бы только 1 строку (первую), поскольку ваша логика должна завершиться в первой строке, где Col4 не равен null

2. Возможно ли иметь несколько ненулевых значений col4 для каждого идентификатора? Если да, верните их все или любую строку?

3. Пожалуйста, посмотрите мою правку.

Ответ №1:

Как насчет этого? Каждый CONDx CTE решает одно условие.

  • COND1 возвращает строки, значение которых COL4 не равно null
  • COND2 возвращает строки, которых COL1 нет в COND1 результирующем наборе, и имеет нули для COL4 (в этом случае количество различных значений = 0) и COL3 = 1
  • COND3 это все, что осталось

Конечным результатом является объединение всех этих.

 SQL> with test (col1, col2, col3, col4) as
  2    (select 100, 'val1', 0, 100  from dual union all
  3     select 100, 'val2', 1, null from dual union all
  4     select 100, 'val3', 0, null from dual union all
  5     select 101, 'val4', 0, null from dual union all
  6     select 101, 'val5', 1, null from dual union all
  7     select 102, 'val6', 0, null from dual
  8    ),
  9  cond1 as
 10    (select col1, col2, col3, col4
 11     From test
 12     where col4 is not null
 13    ),
 14  cond2 as
 15    (select col1, col2, col3, col4
 16     from test t
 17     where t.col1 not in (select col1 from cond1)
 18       and col1 in (select col1
 19                    from test
 20                    group by col1
 21                    having count(distinct col4) = 0
 22                   )
 23       and col3 = 1
 24    ),
 25  cond3 as
 26    (select col1, col2, col3, col4
 27       from test t
 28       where t.col1 not in (select col1 from cond1
 29                            union all
 30                            select col1 from cond2
 31                           )
 32    )
 33  select col1, col2, col3, col4 from cond1
 34  union all
 35  select col1, col2, col3, col4 from cond2
 36  union all
 37  select col1, col2, col3, col4 from cond3
 38  order by col1;

      COL1 COL2       COL3       COL4
---------- ---- ---------- ----------
       100 val1          0        100
       101 val5          1
       102 val6          0

SQL>
 

Комментарии:

1. Если вы добавите одну строку типа: (100, ‘val7’,0,101), она вернет две строки для группы 100. Таким образом, это не работает, как упоминалось в OP.

2. Этого не может произойти @Gen Wan, поскольку в OP сказано: «В каждой группе будет только одна строка, где Col4 имеет ненулевое значение» — в вашем примере это сделало бы 2 строки с COL4, не равным нулю.

3. Мой плохой, я этого не заметил.

4. Никаких проблем вообще 🙂