#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
не равно nullCOND2
возвращает строки, которыхCOL1
нет вCOND1
результирующем наборе, и имеет нули дляCOL4
(в этом случае количество различных значений = 0) иCOL3
= 1COND3
это все, что осталось
Конечным результатом является объединение всех этих.
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. Никаких проблем вообще 🙂