根据条件获取不同的行

huangapple go评论82阅读模式
英文:

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同时有CompletedRescheduled状态,则应选择Rescheduled行,否则选择Completed行。

例如:

ID 1有PlannedCompletedRescheduled状态。输出应如下所示:

一个行为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来实现,并且返回每个idstatus组合的最小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 (&#39;Planned&#39;, &#39;Rescheduled&#39;)
or not exists (
  select 1 from tablename
  where id = t.id and status = &#39;Rescheduled&#39;
)
group by t.id, t.status
order by t.id, t.status

See the demo.<br/>
Results:

&gt; id | desc | status     
&gt; -: | :--- | :----------
&gt;  1 | def  | Planned    
&gt;  1 | ghi  | Rescheduled
&gt;  2 | abc  | Completed  
&gt;  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 = &#39;Planned&#39;)  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 (&#39;Rescheduled&#39;,&#39;Completed&#39;)) 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=&#39;Planned&#39; THEN &#39;Planned&#39;
WHEN description=&#39;Planned&#39;OR description=&#39;Rescheduled&#39; AND (select Count(t.description) from tdata t where t.id=id)&gt;1 THEN &#39;Rescheduled&#39;
ELSE &#39;Completed&#39;
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 &#39;Completed&#39; 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 (&#39;Planned&#39;, &#39;Completed&#39;) or min_status &lt;&gt; &#39;Completed&#39;
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 (&#39;Completed&#39;,&#39;Rescheduled&#39;)
) 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 (&#39;Planned&#39;)

huangapple
  • 本文由 发表于 2020年1月3日 16:00:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/59575049.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定