Reputation: 39
I need your precious help :-)
Imagine the ZAP_TEST_AP table composed of columns A1, B1 and C1 which contains the info shown in the image below
row number | A1 | B1 | C1 |
---|---|---|---|
1 | PRIMARY | 11111 | host1 |
2 | PRIMARY | (null) | host1 |
3 | (null) | (null) | host1 |
4 | PRIMARY | 22222 | host2 |
5 | (null) | 22222 | host2 |
6 | (null) | (null) | host2 |
7 | PRIMARY | (null) | host3 |
8 | (null) | (null) | host3 |
9 | (null) | 44444 | host4 |
10 | (null) | (null) | host4 |
11 | (null) | (null) | host5 |
my goal is to make a query that is able to extract only the rows 1,4,7,9:
row number | A1 | B1 | C1 |
---|---|---|---|
1 | PRIMARY | 11111 | host1 |
4 | PRIMARY | 22222 | host2 |
7 | PRIMARY | (null) | host3 |
9 | (null) | 44444 | host4 |
that is to say:
in the case in which (rows 1,2,3) for the same host1 (field c1) I have three rows where for one there are both a1 and b1, one both null and one where only a1 is set, I would like to extract only the one where both are present --> row 1
in the case in which (rows 4,5,6) for the same host2 (field c1) I have three rows where for one there are both a1 and b1, one both null and one where only b1 is set, I would like to extract only the one where both are present --> row 4
in the case in which (rows 7,8) for the same host3 (field c1) I have two rows where for one they are both null and one where only a1 is set, I would like to extract only the one where a1 is set --> row 7
in the case in which (rows 9,10) for the same host4 (field c1) I have two rows where for one they are both null and one where only b1 is set, I would like to extract only the one where b1 is set --> row 9
in case (row 11) for host5 (field c1) I have only one row and both a1 and b1 are null, I would like it not to be extracted
I hope I have clearly explained my problem :-(
Thanks in advance for your cooperation !!!
Upvotes: 0
Views: 58
Reputation: 1555
You can also use this solution using decode function in the order by clause of row_number analytic function.
select row_number, A1, B1, C1
from (
select row_number, A1, B1, C1
, row_number()over(partition by C1 order by decode(A1, null, 0, 1) + decode(B1, null, 0, 1) desc, row_number ) rnb
, max(decode(A1, null, 0, 1) + decode(B1, null, 0, 1))over(partition by C1)max_presence
from ZAP_TEST_AP
)
where rnb = 1
and max_presence > 0
;
Upvotes: 0
Reputation:
To cover the cases I mentioned in my comments to your question (cases when more than one row may be shown in the output, for the same host), we need to use dense_rank()
rather than row_number()
. I would also write the case
expression in a more user-friendly way, and filter out the rows where both a1
and b1
are null
from the beginning; something like this:
select a1, b1, c1
from (
select a1, b1, c1,
dense_rank() over ( partition by c1
order by case when a1 is not null
and b1 is not null then 2
else 1
end
desc) as rnk
from zap_test_ap z
where a1 is not null or b1 is not null
)
where rnk = 1
;
Upvotes: 1
Reputation: 1269773
You can count the number of null
values and take the first one using row_number()
:
select c1, c2, c3
from (select t.*,
row_number() over (partition by c3
order by (case when c1 is not null then 1 else 0 end) +
(case when c2 is not null then 1 else 0 end) desc
) as seqnum
from t
) t
where seqnum = 1;
Upvotes: 0