web-dev-qa-db-ja.com

PostgreSQLでリセットされた行番号

私はPostgreSQLにこのデータセットを持っています:

 User_id |日付| is_cleared | 
 --------------- + ------------------------- +- ----------- + 
 C | 2016-08-03 18:28:38.37 | 1 | 
 A | 2016-08-01 19:59:36.548 | 0 | 
 A | 2016-08-01 23:38:29.912 | 0 | 
 A | 2016-08-04 19:03:30.585 | 0 | 
 A | 2016-08-08 19:53:20.251 | 0 | 
 A | 2016-08-11 21:00:16.075 | 0 | 
 A | 2016-08-13 21:07:01.336 | 0 | 
 A | 2016-08-15 10:17:32.746 | 0 | 
 A | 2016-08-17 11:54:16.75 | 0 | 
 A | 2016-08-18 21:12:22.717 | 0 | 
 A | 2016-08-21 19:59:26.441 | 0 | 
 A | 2016-08-22 17:19:42.215 | 0 | 
 A | 2016-08-24 20:18:45.516 | 1 | 
 A | 2016-08-27 13:22:33.98 | 1 | 
 A | 2016-08-31 16:09:25.756 | 0 | 
 B | 2016-08-03 21:10:3​​2.945 | 1 | 
 B | 2016-08-05 20:40:55.644 | 1 | 
 B | 2016-08-06 10:59:00.796 | 1 | 
 B | 2016-08-09 22:36:50.674 | 0 | 
 B | 2016-08-11 09:37:21.29 | 1 | 
 B | 2016-08-13 10:15:15.858 | 1 | 
 B | 2016-08-26 09:56:48.937 | 1 | 
 B | 2016-08-29 09:34:13.96 | 1 | 

そして、私はこのような出力が必要です:

 User_id |日付| is_cleared | custom_rank 
 --------------- + ------------------------- +- ---------- + --------- 
 C | 2016-08-03 18:28:38.37 | 1 | 1 
 A | 2016-08-01 19:59:36.548 | 0 | 1 
 A | 2016-08-01 23:38:29.912 | 0 | 2 
 A | 2016-08-04 19:03:30.585 | 0 | 3 
 A | 2016-08-08 19:53:20.251 | 0 | 4 
 A | 2016-08-11 21:00:16.075 | 0 | 5 
 A | 2016-08-13 21:07:01.336 | 0 | 6 
 A | 2016-08-15 10:17:32.746 | 0 | 7 
 A | 2016-08-17 11:54:16.75 | 0 | 8 
 A | 2016-08-18 21:12:22.717 | 0 | 9 
 A | 2016-08-21 19:59:26.441 | 0 | 10 
 A | 2016-08-22 17:19:42.215 | 0 | 11 
 A | 2016-08-24 20:18:45.516 | 1 | 12 
 A | 2016-08-27 13:22:33.98 | 1 | 1 
 A | 2016-08-31 16:09:25.756 | 0 | 1 
 B | 2016-08-03 21:10:3​​2.945 | 1 | 1 
 B | 2016-08-05 20:40:55.644 | 1 | 1 
 B | 2016-08-06 10:59:00.796 | 1 | 1 
 B | 2016-08-09 22:36:50.674 | 0 | 1 
 B | 2016-08-11 09:37:21.29 | 1 | 2 
 B | 2016-08-13 10:15:15.858 | 1 | 1 
 B | 2016-08-26 09:56:48.937 | 1 | 1 
 B | 2016-08-29 09:34:13.96 | 1 | 1 

基本的に、私の目標はis_clearedフラグのゼロの後の最初の「1」を含むゼロの数を数えることです。

データはdateでソートされ、user_idでパーティション化する必要もあります。

3
Kugutsumen

ウィンドウ関数と単一のサブクエリ:

SELECT user_id, date, is_cleared
     , count(*) OVER (PARTITION BY user_id, grp ORDER BY date) AS custom_rank
FROM  (
   SELECT user_id, date, is_cleared
        , count(is_cleared = 1 OR NULL) OVER (PARTITION BY user_id ORDER BY date DESC) AS grp
   FROM   tbl
   ) t
ORDER  BY user_id, date;

ここでの特別な困難:各パーティション1で終わります。最も類似したケースでは、各パーティションは1startします。簡単な解決策は、1の出現を降順でカウントすることです。このように、各パーティションには、次の1が存在する場合、それが含まれます。ボイラ。

関連するすべての列がNOT NULLおよび(user_id, date)一意であると想定します。

基本:

サイド:

  • Bの最初の行はcustom_rank = 1を取得します。 2ではありません。
  • is_clearedは、実際にはbooleanである必要があります。
  • timestamp列は「日付」と呼ばれるべきではありません。
2