如何获得每个岛的第一行和最后一行?
How to get first and last row of each island?
所以我最近在一个问题上得到了很好的帮助。但是,我需要更精确一些,希望在 SQL.
中可行
这是我的最后一个问题:
澄清:
我在那个问题上得到的帮助是给了我每个岛屿的起点。但是,我想要每个岛的开始和停止。
我的细微差别是:
personID | status | unixtime | column d | column e | column f
1 2 213214 x y z
1 2 213325 x y z
1 2 213326 x y z
1 2 213327 x y z
1 2 213328 x y z <-- I want this
1 3 214330 x y z <-- Any of this is OK
1 3 214331 x y z
1 3 214332 x y z <-- I want this or
1 2 324543 x y z <-- I want this
所以我想要岛屿的尽头,而不是岛屿的起点。如果我介于两者之间,那完全没问题,最好是结束。但我真的想要什么是 "right before" 和 "right after" 状态变化,如果这有任何意义的话。这可能是一个特定的状态。
select t.*
from (select t.*,
case when status <> lag(status,1,NULL) over(partition by personID order by unixtime)
then 1
when lag(status,1,NULL) over(partition by personID order by unixtime) is null
then 1
else 0 end as start_status,
case when status <> lead(status,1,NULL) over(partition by personID order by unixtime)
then 1
when lead(status,1,NULL) over(partition by personID order by unixtime) is null
then 1
else 0 end as end_status
from mytable t
) t
where end_status = 1
--or start_status = 1 -- uncomment this line if you want start statuses as well
此查询生成结束或开始分区(或在单行分区的情况下两者)的所有行:
SELECT *
FROM (
SELECT *
, lag(status) OVER w IS DISTINCT FROM status AS partition_start
, lead(status) OVER w IS DISTINCT FROM status AS partition_end
FROM tbl
WINDOW w AS (PARTITION BY personID ORDER BY unixtime)
) sub
WHERE (partition_start OR partition_end)
ORDER BY personID, unixtime;
db<>fiddle here
请注意,对于 PARTITION BY personID
,具有不同 personID
的行不会中断 "island"。我在 fiddle 中向您的测试用例添加了行以演示效果。
如果您的要求不同,则必须定义方式。
所以我最近在一个问题上得到了很好的帮助。但是,我需要更精确一些,希望在 SQL.
中可行这是我的最后一个问题:
澄清:
我在那个问题上得到的帮助是给了我每个岛屿的起点。但是,我想要每个岛的开始和停止。
我的细微差别是:
personID | status | unixtime | column d | column e | column f
1 2 213214 x y z
1 2 213325 x y z
1 2 213326 x y z
1 2 213327 x y z
1 2 213328 x y z <-- I want this
1 3 214330 x y z <-- Any of this is OK
1 3 214331 x y z
1 3 214332 x y z <-- I want this or
1 2 324543 x y z <-- I want this
所以我想要岛屿的尽头,而不是岛屿的起点。如果我介于两者之间,那完全没问题,最好是结束。但我真的想要什么是 "right before" 和 "right after" 状态变化,如果这有任何意义的话。这可能是一个特定的状态。
select t.*
from (select t.*,
case when status <> lag(status,1,NULL) over(partition by personID order by unixtime)
then 1
when lag(status,1,NULL) over(partition by personID order by unixtime) is null
then 1
else 0 end as start_status,
case when status <> lead(status,1,NULL) over(partition by personID order by unixtime)
then 1
when lead(status,1,NULL) over(partition by personID order by unixtime) is null
then 1
else 0 end as end_status
from mytable t
) t
where end_status = 1
--or start_status = 1 -- uncomment this line if you want start statuses as well
此查询生成结束或开始分区(或在单行分区的情况下两者)的所有行:
SELECT *
FROM (
SELECT *
, lag(status) OVER w IS DISTINCT FROM status AS partition_start
, lead(status) OVER w IS DISTINCT FROM status AS partition_end
FROM tbl
WINDOW w AS (PARTITION BY personID ORDER BY unixtime)
) sub
WHERE (partition_start OR partition_end)
ORDER BY personID, unixtime;
db<>fiddle here
请注意,对于 PARTITION BY personID
,具有不同 personID
的行不会中断 "island"。我在 fiddle 中向您的测试用例添加了行以演示效果。
如果您的要求不同,则必须定义方式。