簡體   English   中英

Row_Number 按 id order 按時間戳分區,但按連續行分組

[英]Row_Number partition by id order by timestamp but grouping it by continuous rows

樣本輸入

Name | ID    | Timestamp
-----|-------|-----------------
ABI  | 1     | 2016-01-01 02:00
ABI  | 1     | 2016-01-01 03:00
ABI  | 2     | 2016-01-01 04:00
ABI  | 1     | 2016-01-01 05:00
ABI  | 3     | 2016-01-01 06:00
ABI  | 3     | 2016-01-01 07:00
ABI  | 3     | 2016-01-01 08:00
ABI  | 3     | 2016-01-01 09:00

期望輸出

Name | ID    | Timestamp       |Rank
-----|-------|-----------------|-----
ABI  | 1     | 2016-01-01 02:00|1
ABI  | 1     | 2016-01-01 03:00|2
ABI  | 2     | 2016-01-01 04:00|1
ABI  | 1     | 2016-01-01 05:00|1
ABI  | 1     | 2016-01-01 06:00|2
ABI  | 3     | 2016-01-01 07:00|1
ABI  | 3     | 2016-01-01 08:00|2
ABI  | 3     | 2016-01-01 09:00|3

嘗試查詢

我嘗試使用 ROW_NUMBER() 和 PARTITION BY 按名稱和 ID 進行排名,但按按時間戳排序的連續行對其進行分組。

我試過這個

SELECT Name,
       ID,
       TIMESTAMP(_timestamp) AS TimeStamp,
       ROW_NUMBER() OVER(PARTITION BY Name,ID ORDER BY _timestamp DESC) RANK               
FROM Table_ID

但它按名稱和 ID 排名,而不按連續行分組

非常感謝您的關注和參與。

我假設您使用 MySql。

您可以使用LAG()SUM()窗口函數來創建連續組,然后為每個組創建ROW_NUMBER()

SELECT Name, ID, Timestamp,
       ROW_NUMBER() OVER (PARTITION BY Name, grp ORDER BY Timestamp) `Rank`
FROM (
  SELECT *, SUM(flag) OVER (PARTITION BY Name ORDER BY Timestamp) grp
  FROM (
    SELECT *, COALESCE(ID <> LAG(ID) OVER (PARTITION BY Name ORDER BY Timestamp), 1) flag
    FROM Table_ID
  ) t  
) t 

請參閱演示

這是一種間隙和島嶼問題。 最簡單的解決方案可能是使用行號的差異來識別組,然后使用row_number()作為最終輸出:

select t.*,
       row_number() over (partition by name, id, seqnum - seqnum_2 order by timestamp) as rank
from (select t.*,
             row_number() over (partition by name order by timestamp) as seqnum,
             row_number() over (partition by name, id order by timestamp) as seqnum_2
      from t
     ) t;

使用 MariaDB 10.5.0:

WITH edges AS (
        SELECT t.*
             , COALESCE(name <> LAG(name) OVER (ORDER BY ts) OR id <> LAG(id) OVER (ORDER BY ts), 1) AS edge
          FROM runs AS t
     )
   , grps AS (
        SELECT t.*
             , SUM(edge) OVER (ORDER BY ts) AS grp
          FROM edges AS t
     )
SELECT grps.*
     , ROW_NUMBER() OVER (PARTITION BY grp ORDER BY ts) AS actual
  FROM grps
;

+------+------+---------------------+----------+------+------+--------+
| name | id   | ts                  | expected | edge | grp  | actual |
+------+------+---------------------+----------+------+------+--------+
| ABI  |    1 | 2016-01-01 02:00:00 |        1 |    1 |    1 |      1 |
| ABI  |    1 | 2016-01-01 03:00:00 |        2 |    0 |    1 |      2 |
| ABI  |    2 | 2016-01-01 04:00:00 |        1 |    1 |    2 |      1 |
| ABI  |    1 | 2016-01-01 05:00:00 |        1 |    1 |    3 |      1 |
| ABI  |    1 | 2016-01-01 06:00:00 |        2 |    0 |    3 |      2 |
| ABI  |    3 | 2016-01-01 07:00:00 |        1 |    1 |    4 |      1 |
| ABI  |    3 | 2016-01-01 08:00:00 |        2 |    0 |    4 |      2 |
| ABI  |    3 | 2016-01-01 09:00:00 |        3 |    0 |    4 |      3 |
+------+------+---------------------+----------+------+------+--------+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM