I have a table that looks like this:
ID Type Value
A Z01 10
A Z09 20
B Z01 30
C Z01 40
D Z09 50
E Z10 60
For each ID I would like to retrieve a value. Ideally the value should come from the row with type Z01. However, if Z01 is not available I'll pick Z09 instead. If nothing is available I would like to select nothing.
The result would look like this:
Id Type Value
A Z01 10
B Z01 30
C Z01 40
D Z09 50
How can I accomplish this with T-SQL?
This should give you what you want:
select *
from table t
where 1 = case
when t.type = 'Z01'
then 1
when t.type = 'Z09'
and not exists (select 1 from table where id = t.id and type = 'Z01')
then 1
else 0
end
An alternative, with using a more common approach is (re-writing the CASE
expression):
select *
from table
where type = 'Z01'
OR (type = 'Z09' and not exists (select 1 from table where id = t.id and type = 'Z01'))
An obvious sargable
approach (which will make your query use the appropriate index on your table, if it exists) would be:
select *
from table
where type = `Z01`
union all
select *
from table
where type = `Z09`
and not exists (select 1 from table where id = t.id and type = 'Z01')
And when I'm saying index I'm talking about a non-clustered index on the type
column.
You can use query like this
;WITH cte
AS (SELECT
*, ROW_NUMBER() OVER (PARTITION BY id ORDER BY type) AS rn
FROM yourtable
WHERE type IN ('Z01', 'Z09'))
SELECT
id, type, value
FROM cte
WHERE rn = 1
I would use window functions:
select t.*
from (select t.*,
row_number() over (partition by id
order by (case when type = 'Z01' then 1
when type = 'Z09' then 2
end)
) as seqnum
from t
) t
where seqnum = 1;
I don't fully understand teh statement "if nothing is available, then choose nothing". If, by this, you mean you want 'Z01', 'Z09' or nothing at all, then just do:
select t.*
from (select t.*,
row_number() over (partition by id order by type) as seqnum
from t
where type in ('Z01', 'Z09')
) t
where seqnum = 1;
The where
clause does the filtering, and you can just order by the type alphabetically.
Then try this
Select distinct a.id,
coalesce(t1.type, t9.type) type,
case when t1.type is not null
then t1.value else t9.value end value
From table a
left join table t1
on t1.id = a.id
and t1.type = 'Z01'
left join table t9
on t9.id = a.id
and t9.type = 'Z09'
Where a.type in ('Z01', 'Z09') -- < -- this last to eliminate row E
Something like this:
select distinct
base.Id,
Coalesce(z01.Type, any.Type) Type,
Coalesce(z01.Value, any.Value)
from (select distinct id from [table]) base
left outer join [table] z01
on z01.id = base.id
and z01.Type = 'Z01'
left outer join [table] any
on any.id = base.id
and any.type != 'Z01'
Start with a WHERE
clause. Select only entries with Z01 and Z09. Then use ROW_NUMBER
to rank your rows and keep the best.
select id, type, value
from
(
select
id, type, value,
row_number()
over (partition by id order by case when type = 'Z01' then 1 else 2 end) as rn
from mytable
where type in ('Z01','Z09')
) ranked
where rn = 1;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.