针对给定用例建议 SQL 查询
Suggest SQL query for given use case
原文Table
Id | Time | Status
------------------
1 | 5 | T
1 | 6 | F
2 | 3 | F
1 | 2 | F
2 | 4 | T
3 | 7 | F
2 | 3 | T
3 | 1 | F
4 | 7 | H
4 | 6 | S
4 | 5 | F
4 | 4 | T
5 | 5 | S
5 | 6 | F
预计Table
Id | Time | Status
------------------
1 | 6 | F
3 | 7 | F
4 | 5 | F
我想要所有状态为 F 但时间应该最长的不同 ID,如果对于给定的最长时间,任何 ID 状态为 T,则不应选择该 ID。此外,只有那些至少有一个 T 的 ID 才应该被选中。例如,4 不会被选中,因为它没有任何 'T' 作为状态。
请帮助编写 SQL 查询。
试试下面的方法-
select * from tablename t
where time = (select max(time) from tablename t1 where t.id=t1.id and Status='F')
and Status='F'
以下应该有效
select id,max(time) as time,status
from table
where status='F'
group by id,status
select id, max(time), status
from stuff s
where status = 'F'
and id not in (
select id
from stuff s2
where s2.id = s.id
and s2.time > s.time
and s2.status = 'T')
group by id, status;
你可以看到 Fiddle here.
据我了解,您想找到状态为F的每个ID(max(time)
)的最高时间,但前提是没有以后的记录状态为[=17] =].子查询过滤掉存在状态为 T 的较晚记录的记录。
WITH MAX_TIME_ID AS (
SELECT
ID
,MAX(TIME) AS MAX_TIME
GROUP BY
ID
)
SELECT
O.*
FROM
ORIGINAL_TABLE O
INNER JOIN
MAX_TIME_ID MAX
ON
O.ID = MAX.ID
WHERE
O.STATUS = 'F'
CTE 将找到每个 ID 的最长时间,只有当最新的是 'F'.
时,使用状态上的 where 子句的内部连接才会 select 它
您可以在 WHERE
子句中使用 EXISTS
和 NOT EXISTS
:
select t.*
from tablename t
where t.status = 'F'
and exists (select 1 from tablename where id = t.id and status = 'T')
and not exists (
select 1
from tablename
where id = t.id and status in ('F', 'T') and time > t.time
)
参见demo。
结果:
| Id | Time | Status |
| --- | ---- | ------ |
| 1 | 6 | F |
| 4 | 5 | F |
我只会使用 window 函数:
select t.*
from (select t.*
row_number() over (partition by id order by time desc) as seqnum,
sum(case when status = 'T' then 1 else 0 end) over (partition by id) as num_t
from t
) t
where num_t > 0 and
seqnum = 1 and status = 'F';
还有另一种有趣的方法可以通过聚合来做到这一点:
select id, max(time) as time, 'F' as status
from t
group by id
having sum(case when status = 'T' then 1 else 0 end) > 0 and
max(time) = max(case when status 'F' then time end);
原文Table
Id | Time | Status
------------------
1 | 5 | T
1 | 6 | F
2 | 3 | F
1 | 2 | F
2 | 4 | T
3 | 7 | F
2 | 3 | T
3 | 1 | F
4 | 7 | H
4 | 6 | S
4 | 5 | F
4 | 4 | T
5 | 5 | S
5 | 6 | F
预计Table
Id | Time | Status
------------------
1 | 6 | F
3 | 7 | F
4 | 5 | F
我想要所有状态为 F 但时间应该最长的不同 ID,如果对于给定的最长时间,任何 ID 状态为 T,则不应选择该 ID。此外,只有那些至少有一个 T 的 ID 才应该被选中。例如,4 不会被选中,因为它没有任何 'T' 作为状态。
请帮助编写 SQL 查询。
试试下面的方法-
select * from tablename t
where time = (select max(time) from tablename t1 where t.id=t1.id and Status='F')
and Status='F'
以下应该有效
select id,max(time) as time,status
from table
where status='F'
group by id,status
select id, max(time), status
from stuff s
where status = 'F'
and id not in (
select id
from stuff s2
where s2.id = s.id
and s2.time > s.time
and s2.status = 'T')
group by id, status;
你可以看到 Fiddle here.
据我了解,您想找到状态为F的每个ID(max(time)
)的最高时间,但前提是没有以后的记录状态为[=17] =].子查询过滤掉存在状态为 T 的较晚记录的记录。
WITH MAX_TIME_ID AS (
SELECT
ID
,MAX(TIME) AS MAX_TIME
GROUP BY
ID
)
SELECT
O.*
FROM
ORIGINAL_TABLE O
INNER JOIN
MAX_TIME_ID MAX
ON
O.ID = MAX.ID
WHERE
O.STATUS = 'F'
CTE 将找到每个 ID 的最长时间,只有当最新的是 'F'.
时,使用状态上的 where 子句的内部连接才会 select 它您可以在 WHERE
子句中使用 EXISTS
和 NOT EXISTS
:
select t.*
from tablename t
where t.status = 'F'
and exists (select 1 from tablename where id = t.id and status = 'T')
and not exists (
select 1
from tablename
where id = t.id and status in ('F', 'T') and time > t.time
)
参见demo。
结果:
| Id | Time | Status |
| --- | ---- | ------ |
| 1 | 6 | F |
| 4 | 5 | F |
我只会使用 window 函数:
select t.*
from (select t.*
row_number() over (partition by id order by time desc) as seqnum,
sum(case when status = 'T' then 1 else 0 end) over (partition by id) as num_t
from t
) t
where num_t > 0 and
seqnum = 1 and status = 'F';
还有另一种有趣的方法可以通过聚合来做到这一点:
select id, max(time) as time, 'F' as status
from t
group by id
having sum(case when status = 'T' then 1 else 0 end) > 0 and
max(time) = max(case when status 'F' then time end);