英文:
How to get distinct row based on criteria
问题
我有一个包含以下数据的表格
ID | Desc | Status
------+------+------------
1 | abc | Completed
1 | abc | Completed
1 | def | Planned
1 | def | Planned
1 | ghi | Rescheduled
1 | ghi | Rescheduled
2 | abc | Completed
2 | def | Planned
2 | ghi | Planned
我需要根据状态获取每个ID的一行数据。对于Planned
状态,每个ID应该有一行,对于其他状态,如果一个ID同时有Completed
和Rescheduled
状态,则应选择Rescheduled
行,否则选择Completed
行。
例如:
ID 1有Planned
,Completed
和Rescheduled
状态。输出应如下所示:
一个行为ID=1的Planned
和一个行为ID=1的Rescheduled
。
ID | Desc | Status
------+------+------------
1 | ghi | Rescheduled
1 | def | Planned
2 | abc | Completed
2 | def | Planned
英文:
I have table with data like this
<pre>
ID | Desc | Status
------+------+------------
1 | abc | Completed
1 | abc | Completed
1 | def | Planned
1 | def | Planned
1 | ghi | Rescheduled
1 | ghi | Rescheduled
2 | abc | Completed
2 | def | Planned
2 | ghi | Planned
</pre>
I need to get one row for each ID based on Status. One row for Planned
and for other, if an ID has both status Completed
& Rescheduled
, then Rescheduled
row must be selected or else Completed
e.g.
ID 1 has Planned
, Completed
& Rescheduled
status. The output should be as below
one row Planned
for ID=1 & one row "Rescheduled" for ID=1
<pre>
ID | Desc | Status
------+------+------------
1 | ghi | Rescheduled
1 | def | Planned
2 | abc | Completed
2 | def | Planned
</pre>
答案1
得分: 1
你可以使用NOT EXISTS
来实现,并且返回每个id
和status
组合的最小desc
值(如您期望的输出):
select t.id, min(t.[desc]) [desc], t.status
from tablename t
where status in ('Planned', 'Rescheduled')
or not exists (
select 1 from tablename
where id = t.id and status = 'Rescheduled'
)
group by t.id, t.status
order by t.id, t.status
结果:
> id | desc | status
> -: | :--- | :----------
> 1 | def | Planned
> 1 | ghi | Rescheduled
> 2 | abc | Completed
> 2 | def | Planned
演示链接。
英文:
Your can do it with NOT EXISTS
and then return (as your expected output) the minimum value of desc
for each combination of id
and status
:
select t.id, min(t.[desc]) [desc], t.status
from tablename t
where status in ('Planned', 'Rescheduled')
or not exists (
select 1 from tablename
where id = t.id and status = 'Rescheduled'
)
group by t.id, t.status
order by t.id, t.status
See the demo.<br/>
Results:
> id | desc | status
> -: | :--- | :----------
> 1 | def | Planned
> 1 | ghi | Rescheduled
> 2 | abc | Completed
> 2 | def | Planned
答案2
得分: 1
你可以尝试这个:
select id, desc, status, 1 count from (
select id, desc, status, ROW_NUMBER() over (partition by id) rownum from (
select distinct id, desc, status, 1 count
from tablename where status = 'Planned'
) x
) y
where rownum = 1
union all
select id, desc, status, 1 from (
select id, desc, status, ROW_NUMBER() over (partition by id order by status desc) rownum from (
select distinct id, desc, status from tablename where status in ('Rescheduled','Completed')
) x
) y
where rownum = 1
order by 1,2,3
英文:
you can try this
select id, desc, status, 1 count from(
select id, desc, status, ROW_NUMBER() over (partition by id) rownum from(
select distinct id, desc, status, 1 count
from tablename where status = 'Planned') x ) y
where rownum = 1
union all
select id, desc, status, 1 from(
select id, desc, status, ROW_NUMBER() over (partition by id order by status desc) rownum from(
select distinct id, desc, status from tablename where status in ('Rescheduled','Completed')) x ) y
where rownum = 1
order by 1,2,3
答案3
得分: 0
你可以使用CTE
来删除重复的记录,然后应用CASE WHEN THEN
来获得所需的结果,如下所示:
WITH CTE_Result AS
(
SELECT DISTINCT Id, description, status
FROM tdata
)
SELECT Id,
CASE
WHEN description='Planned' THEN 'Planned'
WHEN description='Planned' OR description='Rescheduled' AND (SELECT COUNT(t.description) FROM tdata t WHERE t.id=id)>1 THEN 'Rescheduled'
ELSE 'Completed'
END AS description,
status
FROM CTE_Result;
示例链接:http://www.sqlfiddle.com/#!18/cb394/49
英文:
You can use CTE
to remove duplicate records, then apply CASE WHEN THEN
to get desired results like :
WITH CTE_Result AS
(
select distinct Id,description, status
from tdata
)
select Id,
CASE
WHEN description='Planned' THEN 'Planned'
WHEN description='Planned'OR description='Rescheduled' AND (select Count(t.description) from tdata t where t.id=id)>1 THEN 'Rescheduled'
ELSE 'Completed'
END as description,
status
from CTE_Result;
Sample fiddle is http://www.sqlfiddle.com/#!18/cb394/49
答案4
得分: 0
以下是翻译好的部分:
您可以查看每个ID的最低状态,即'已完成'
或非'已完成'
:
with data as
(
select
id, status, min([Desc]) as description, min(status) over (partition by id) as min_status
from mytable
group by id, status
)
select id, status, description
from data
where status in ('Planned', 'Completed') or min_status <> 'Completed'
order by id, status;
英文:
You can look at the minimum status per ID, which is either 'Completed'
or not:
with data as
(
select
id, status, min([Desc]) as description, min(status) over (partition by id) as min_status
from mytable
group by id, status
)
select id, status, description
from data
where status in ('Planned', 'Completed') or min_status <> 'Completed'
order by id, status;
答案5
得分: 0
我从@Krishna Muppalla和@Thorsten Kettner那里得出了使用逻辑的结论。感谢大家的建议。
select * from
(
select
distinct ID
,Desc
,Status
,max(Status) over (partition by ID, desc) as New_Status
from tdata
where Status in ('Completed','Rescheduled')
) A
where A.Status = A.New_Status
UNION
select
distinct ID
,Desc
,Status
,max(Status) over (partition by ID, desc) as New_Status
from tdata
where Status in ('Planned')
英文:
I figured out using logic from @Krishna Muppalla and @Thorsten Kettner. Thanks you all for your suggestions.
select * from
(
select
distinct ID
,Desc
,Status
,max(Status) over (partition by ID, desc) as New_Status
from tdata
where Status in ('Completed','Rescheduled')
) A
where A.Status = A.New_Status
UNION
select
distinct ID
,Desc
,Status
,max(Status) over (partition by ID, desc) as New_Status
from tdata
where Status in ('Planned')
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论