Reputation: 1570
I realise the title to this question may be vague but I am not sure how to phrase it. I have the following table:
i_id option p_id
---- ------ ----
1 A 4
1 B 8
1 C 6
2 B 3
2 C 5
3 A 7
3 B 3
4 E 11
How do I select a row based on the value of the option
column for each unique i_id
: if 'C'
exists, select the row, else select row with 'B'
else with 'A'
so that result set is:
i_id option p_id
---- ------ ----
1 C 6
2 C 5
3 B 3
Upvotes: 2
Views: 215
Reputation: 30237
Well, I would suggest that this problem can be made easier if you can assign a numeric "score" to each letter, such that "better" letters have higher scores. Then you can use MAX to find, for each group, the row with the highest "score" for the option. Since 'A' < 'B' < 'C', we could cheat here and use option as the score, and thus:
SELECT t1.i_id, t1.option, t1.p_id
FROM thetable t1
INNER JOIN (SELECT t2.i_id, MAX(option)
FROM thetable t2
GROUP BY t2.i_id) AS maximums
ON t1.i_id = maximums.i_id
WHERE option != 'D'
This assumes that {i_id, option}
is a natural key of the table (i.e., that no two rows will have the same combination of values for those two columns; or, alternatively, that you have an uniqueness constraint on that pair of columns).
Upvotes: 1
Reputation: 78210
select i_id, option, p_id
from (
select
i_id,
option,
p_id,
row_number() over (partition by i_id order by case option when 'C' then 0 when 'B' then 1 when 'A' then 2 end) takeme
from thetable
where option in ('A', 'B', 'C')
) foo
where takeme = 1
Upvotes: 2
Reputation: 45325
create table t2 (
id int,
options varchar(1),
pid int
)
insert into t2 values(1, 'A', 4)
insert into t2 values(1, 'B', 8)
insert into t2 values(1, 'C', 6)
insert into t2 values(1, 'E', 7)
select t2.* from t2,
(select id, MAX(options) as op from t2
where options <> 'E'
group by id) t
where t2.id = t.id and t2.options = t.op
Upvotes: 1
Reputation: 17570
This will give you the values ordered by C, B, A, while removing any i_id record that does not have one of these values.
WITH ranked AS
(
SELECT i_id, [option], p_id
, ROW_NUMBER() OVER (PARTITION BY i_id ORDER BY CASE [option]
WHEN 'C' THEN 1
WHEN 'B' THEN 2
WHEN 'A' THEN 3
ELSE 4
END) AS rowNumber
FROM yourTable
WHERE [option] IN ('A', 'B', 'C')
)
SELECT r.i_id, r.[option], r.p_id
FROM ranked AS r
WHERE r.rowNumber = 1
Upvotes: 2