SQL - 从上次重复出现的状态获取
SQL - Get from last reoccurring status
我有一个 table 如下所示
#ID ResultStatus StatusDate
100 F 9/01/2017
100 S 6/01/2017
100 F 2/01/2017
300 F 7/01/2017
300 F 3/01/2017
300 S 1/01/2017
500 S 7/01/2017
800 F 7/01/2017
800 S 3/01/2017
800 F 2/01/2017
800 S 1/01/2017
我想获取最后一条 'S' 记录之后的所有 'F' 记录。
它应该只是 return
对于 ID 100,2017 年 9 月 1 日的记录
对于 ID 300,3/01/2017 和 7/01/2017 的记录
对于 ID 500 什么都没有,因为没有 F
对于 ID 800,2017 年 7 月 1 日的记录
选择上次成功后的所有失败。
我正在使用 Teradata SQL,但任何 SQL 帮助将不胜感激。
标准SQL方法是:
select t.*
from t
where t.resultstatus = 'F' and
t.statusdate > (select max(t2.statusdate)
from t t2
where t2.resultstatus = 'S' and t2.id = t.id
);
但是,我也倾向于使用 window 函数来做到这一点:
select t.*
from (select t.*,
max(case when t.resultstatus = 'S' then statusdate end) over (partition by id) as max_s
from t
) t
where t.resultstatus = 'F' and
t.statusdate > max_s;
如果在没有 S
时想要所有行,则将 where
更改为:
where resultstatus = 'F' and
(statusdate > max_s or max_s is null);
编辑:
以下可能也有效:
select t.*
from t
qualify t.resultstatus = 'F' and
t.statusdate > max(case when t.resultstatus = 'S' then statusdate end) over (partition by id);
通过使用CROSS JOIN,解析函数ROW_NUMBER()我们可以解决这个问题。下面 link 中的 SQL 解决方案将对其进行详细解释。
DDL :-
CREATE TABLE Sample( ID INT, ResultStatus VARCHAR(10), StatusDate DATE);
INSERT INTO Sample VALUES(100,'F','09-01-2017');
INSERT INTO Sample VALUES(100,'S','06-01-2017');
INSERT INTO Sample VALUES(100,'F','02-01-2017');
INSERT INTO Sample VALUES(300,'F','07-01-2017');
INSERT INTO Sample VALUES(300,'F','03-01-2017');
INSERT INTO Sample VALUES(300,'S','01-01-2017');
INSERT INTO Sample VALUES(500,'F','07-01-2017');
INSERT INTO Sample VALUES(800,'F','07-01-2017');
INSERT INTO Sample VALUES(800,'S','03-01-2017');
INSERT INTO Sample VALUES(800,'F','02-01-2017');
INSERT INTO Sample VALUES(800,'S','01-01-2017');
SQL :-
SELECT B.id,B.ResultStatus,B.StatusDate
FROM
(
SELECT *,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY StatusDate DESC ) AS rn,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY ResultStatus DESC,StatusDate ) AS rn_status
FROM Sample ) A
CROSS JOIN
(
SELECT *,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY StatusDate DESC ) AS rn,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY ResultStatus DESC,StatusDate DESC ) AS rn_status
FROM Sample
) B
WHERE A.ResultStatus = 'S'
AND A.ResultStatus != B.ResultStatus
AND B.StatusDate > A.StatusDate
AND A.ID = B.ID
AND A.rn > B.rn
AND A.rn_status = 1
AND B.rn_status - B.rn = 1
;
我有一个 table 如下所示
#ID ResultStatus StatusDate
100 F 9/01/2017
100 S 6/01/2017
100 F 2/01/2017
300 F 7/01/2017
300 F 3/01/2017
300 S 1/01/2017
500 S 7/01/2017
800 F 7/01/2017
800 S 3/01/2017
800 F 2/01/2017
800 S 1/01/2017
我想获取最后一条 'S' 记录之后的所有 'F' 记录。 它应该只是 return
对于 ID 100,2017 年 9 月 1 日的记录
对于 ID 300,3/01/2017 和 7/01/2017 的记录
对于 ID 500 什么都没有,因为没有 F
对于 ID 800,2017 年 7 月 1 日的记录
选择上次成功后的所有失败。
我正在使用 Teradata SQL,但任何 SQL 帮助将不胜感激。
标准SQL方法是:
select t.*
from t
where t.resultstatus = 'F' and
t.statusdate > (select max(t2.statusdate)
from t t2
where t2.resultstatus = 'S' and t2.id = t.id
);
但是,我也倾向于使用 window 函数来做到这一点:
select t.*
from (select t.*,
max(case when t.resultstatus = 'S' then statusdate end) over (partition by id) as max_s
from t
) t
where t.resultstatus = 'F' and
t.statusdate > max_s;
如果在没有 S
时想要所有行,则将 where
更改为:
where resultstatus = 'F' and
(statusdate > max_s or max_s is null);
编辑:
以下可能也有效:
select t.*
from t
qualify t.resultstatus = 'F' and
t.statusdate > max(case when t.resultstatus = 'S' then statusdate end) over (partition by id);
通过使用CROSS JOIN,解析函数ROW_NUMBER()我们可以解决这个问题。下面 link 中的 SQL 解决方案将对其进行详细解释。
DDL :-
CREATE TABLE Sample( ID INT, ResultStatus VARCHAR(10), StatusDate DATE);
INSERT INTO Sample VALUES(100,'F','09-01-2017');
INSERT INTO Sample VALUES(100,'S','06-01-2017');
INSERT INTO Sample VALUES(100,'F','02-01-2017');
INSERT INTO Sample VALUES(300,'F','07-01-2017');
INSERT INTO Sample VALUES(300,'F','03-01-2017');
INSERT INTO Sample VALUES(300,'S','01-01-2017');
INSERT INTO Sample VALUES(500,'F','07-01-2017');
INSERT INTO Sample VALUES(800,'F','07-01-2017');
INSERT INTO Sample VALUES(800,'S','03-01-2017');
INSERT INTO Sample VALUES(800,'F','02-01-2017');
INSERT INTO Sample VALUES(800,'S','01-01-2017');
SQL :-
SELECT B.id,B.ResultStatus,B.StatusDate
FROM
(
SELECT *,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY StatusDate DESC ) AS rn,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY ResultStatus DESC,StatusDate ) AS rn_status
FROM Sample ) A
CROSS JOIN
(
SELECT *,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY StatusDate DESC ) AS rn,
ROW_NUMBER() OVER( PARTITION BY ID ORDER BY ResultStatus DESC,StatusDate DESC ) AS rn_status
FROM Sample
) B
WHERE A.ResultStatus = 'S'
AND A.ResultStatus != B.ResultStatus
AND B.StatusDate > A.StatusDate
AND A.ID = B.ID
AND A.rn > B.rn
AND A.rn_status = 1
AND B.rn_status - B.rn = 1
;