英文:
How to flag all records for a date when at least two records for that date have same duration OR at least one record has 0 durtation
问题
日期 | 代码 | 时长 | 标记 |
---|---|---|---|
4/2/23 | AB | 510 | 是 |
4/2/23 | SH | 510 | 是 |
4/2/23 | B2 | 15 | 是 |
同时包括0
日期 | 代码 | 时长 | 标记 |
---|---|---|---|
4/2/23 | AB | 0 | 是 |
4/2/23 | SH | 510 | 是 |
4/2/23 | B2 | 15 | 是 |
期望结果:
日期 | 代码 | 时长 | 标记 |
---|---|---|---|
4/2/23 | AB | 510 | 是 |
4/2/23 | SH | 510 | 是 |
4/2/23 | B2 | 15 | 是 |
或者
日期 | 代码 | 时长 | 标记 |
---|---|---|---|
4/2/23 | AB | 0 | 是 |
4/2/23 | SH | 510 | 是 |
4/2/23 | B2 | 15 | 是 |
英文:
I need to flag records for a date when there are the same duration or at least one of the records have 0 duration. CODE SH is the duration being matched to or if another records has a 0 duration. Example Records being analyzed:
Date | Code | Duration |
---|---|---|
4/2/23 | AB | 510 |
4/2/23 | SH | 510 |
4/2/23 | B2 | 15 |
also with 0
Date | Code | Duration |
---|---|---|
4/2/23 | AB | 0 |
4/2/23 | SH | 510 |
4/2/23 | B2 | 15 |
Expect this:
Date | Code | Duration | FLAG |
---|---|---|---|
4/2/23 | AB | 510 | Y |
4/2/23 | SH | 510 | Y |
4/2/23 | B2 | 15 | Y |
OR
Date | Code | Duration | FLAG |
---|---|---|---|
4/2/23 | AB | 0 | Y |
4/2/23 | SH | 510 | Y |
4/2/23 | B2 | 15 | Y |
I was going to do an analytic function that counted records using code and date as partition.
count(1) over (partition by date,code,duration)
but then realized how do I handle 0's as well ? Thanks for any help.
答案1
得分: 2
以下是翻译好的部分:
You may use count and min window functions as the following:
with t as
(
select tb.*,
count(*) over (partition by date_, code, Duration) cnt,
min(Duration) over (partition by date_, code) min_dur
from tbl tb
)
select t.date_, t.code, t.duration,
case
when min_dur = 0 or -- there is a 0 duration
max(cnt) over (partition by date_, code) > 1 -- when there are the same durations in multiple rows.
then 'Y' else 'N'
end as flg
from t
<details>
<summary>英文:</summary>
You may use count and min window functions as the following:
with t as
(
select tb.*,
count(*) over (partition by date_, code, Duration) cnt,
min(Duration) over (partition by date_, code) min_dur
from tbl tb
)
select t.date_, t.code, t.duration,
case
when min_dur = 0 or -- there is a 0 duration
max(cnt) over (partition by date_, code) > 1 -- when there are the same durations in multiple rows.
then 'Y' else 'N'
end as flg
from t
[demo][1]
[1]: https://dbfiddle.uk/gPFKJ8Q0
</details>
# 答案2
**得分**: 1
我有些累,可能有一种更简单的方法我现在没能看到,但你可以对比上海和非上海的日期/持续时间,然后将持续时间为零的日期相加。
选择日期、代码、持续时间
来自我的表
其中日期在
(
选择日期从
(
选择日期、持续时间
来自我的表
其中代码 = 'SH'
交集
选择日期、持续时间
来自我的表
其中代码 <> 'SH'
联合全部
选择日期、持续时间
来自我的表
其中持续时间 = 0
)
);
或
选择日期、代码、持续时间
来自我的表 t
其中存在
(
选择日期、持续时间
来自我的表 t2
其中t2.日期 = t.日期 和 t2.代码 = 'SH'
交集
选择日期、持续时间
来自我的表 t3
其中t3.日期 = t.日期 和 t3.代码 <> 'SH'
)
或日期在
(
选择日期
来自我的表
其中持续时间 = 0
);
<details>
<summary>英文:</summary>
I am a bit tired, so there might be a much simpler method that I fail to see right now, but you can just intersect date/duration for SH and non-SH and then add the dates with a zero duration.
select date, code, duration
from mytable
where date in
(
select date from
(
select date, duration
from mytable
where code = 'SH'
intersect
select date, duration
from mytable
where code <> 'SH'
union all
select date, duration
from mytable
where duration = 0
)
);
or
select date, code, duration
from mytable t
where exists
(
select date, duration
from mytable t2
where t2.date = t.date and t2.code = 'SH'
intersect
select date, duration
from mytable t3
where t3.date = t.date and t3.code <> 'SH'
)
or date in
(
select date
from mytable
where duration = 0
);
</details>
# 答案3
**得分**: 1
ahmed的建议帮助我得到我所需的东西。我不得不稍微调整它,但它有效。实际上,我还需要一个额外的分区字段,用于员工ID。以下是我想出来的内容:
这个公共表达式查找不是SH的最大持续时间和最小持续时间。
,t as
(
select tb.*,
max(case when code <> 'SH' then duration end) over (partition by nom_date, emp_id) mx,
min(Duration) over (partition by nom_date,emp_id) min_dur
from scd tb
)
这些标记了我不需要的记录:
select
to_char(nom_date,'MM-YYYY') Mnth,
nom_date,
EMP_ID,
from
(
select t.nom_date,t.emp_id, t.code, t.duration,
case
when min_dur = 0 or -- there is a 0 duration
max(case when code = 'SH' THEN duration end) over (partition by nom_date,emp_id) = max(mx) over (partition by nom_date,emp_id) -- when there are the same durations in multiple rows.
then 'Y' else 'N'
end as flg
from t
)
where FLG = 'N' and CODE = 'SH'
<details>
<summary>英文:</summary>
ahmed's tip help get me what I needed. I had to tweak it a bit but it worked. I actually needed one more partitioned field as well for emp id. Here's what I came up with:
This cte finds the max duration which is not SH and min duration.
,t as
(
select tb.*,
max(case when code <> 'SH' then duration end) over (partition by nom_date, emp_id) mx,
min(Duration) over (partition by nom_date,emp_id) min_dur
from scd tb
)
This flags records I do not need:
select
to_char(nom_date,'MM-YYYY')Mnth,
nom_date,
EMP_ID,
from
(
select t.nom_date,t.emp_id, t.code, t.duration,
case
when min_dur = 0 or -- there is a 0 duration
max(case when code = 'SH' THEN duration end) over (partition by nom_date,emp_id) = max(mx) over (partition by nom_date,emp_id) -- when there are the same durations in multiple rows.
then 'Y' else 'N'
end as flg
from t
)
where FLG = 'N' and CODE = 'SH'
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论