【问题标题】:PostgreSQL - rank over rows listed in blocks of 0 and 1PostgreSQL - 对 0 和 1 块中列出的行进行排名
【发布时间】:2017-07-28 06:32:04
【问题描述】:

我有一个看起来像这样的表:

id     code      date1         date2         block
--------------------------------------------------
20     1234      2017-07-01    2017-07-31    1
15     1234      2017-06-01    2017-06-30    1
13     1234      2017-05-01    2017-05-31    0
11     1234      2017-03-01    2017-03-31    0
9      1234      2017-02-01    2017-02-28    1
8      1234      2017-01-01    2017-01-31    0
7      1234      2016-11-01    2016-11-31    0
6      1234      2016-10-01    2016-10-31    1
2      1234      2016-09-01    2016-09-31    1

我需要根据 0 和 1 的块对行进行排名,例如:

id     code      date1         date2         block     desired_rank
-------------------------------------------------------------------
20     1234      2017-07-01    2017-07-31    1         1
15     1234      2017-06-01    2017-06-30    1         1
13     1234      2017-05-01    2017-05-31    0         2
11     1234      2017-03-01    2017-03-31    0         2
9      1234      2017-02-01    2017-02-28    1         3
8      1234      2017-01-01    2017-01-31    0         4
7      1234      2016-11-01    2016-11-31    0         4
6      1234      2016-10-01    2016-10-31    1         5
2      1234      2016-09-01    2016-09-31    1         5

我尝试过使用rank()和dense_rank(),但我最终得到的结果是:

id     code      date1         date2         block     dense_rank()
-------------------------------------------------------------------
20     1234      2017-07-01    2017-07-31    1         1
15     1234      2017-06-01    2017-06-30    1         2
13     1234      2017-05-01    2017-05-31    0         1
11     1234      2017-03-01    2017-03-31    0         2
9      1234      2017-02-01    2017-02-28    1         3
8      1234      2017-01-01    2017-01-31    0         3
7      1234      2016-11-01    2016-11-31    0         4
6      1234      2016-10-01    2016-10-31    1         4
2      1234      2016-09-01    2016-09-31    1         5

在最后一个表中,排名不关心行,它只是将所有的 1 和 0 作为一个单元,并设置从第一个 1 和 0 开始的升序计数。 我的查询是这样的:

CREATE TEMP TABLE data (id integer,code text, date1 date, date2 date, block integer);

INSERT INTO data VALUES
(20,'1234', '2017-07-01','2017-07-31',1),
(15,'1234', '2017-06-01','2017-06-30',1),
(13,'1234', '2017-05-01','2017-05-31',0),
(11,'1234', '2017-03-01','2017-03-31',0),
(9, '1234', '2017-02-01','2017-02-28',1),
(8, '1234', '2017-01-01','2017-01-31',0),
(7, '1234', '2016-11-01','2016-11-30',0),
(6, '1234', '2016-10-01','2016-10-31',1),
(2, '1234', '2016-09-01','2016-09-30',1);

SELECT *,dense_rank() OVER (PARTITION BY code,block ORDER BY date2 DESC)
FROM data 
ORDER BY date2 DESC;

顺便说一下,数据库在postgreSQL中。

我希望有一个解决方法...谢谢:)

编辑:请注意,0 和 1 的块不相等。

【问题讨论】:

  • 试试这个,从分区中删除块并使用日期2,块的顺序。

标签: sql postgresql window-functions rank dense-rank


【解决方案1】:

没有办法使用 single 窗口函数得到这个结果:

SELECT *,
   Sum(flag) -- now sum the 0/1 to create the "rank"
   Over (PARTITION BY code
         ORDER BY date2 DESC)
FROM
 (
   SELECT *,
      CASE
         WHEN Lag(block) -- check if this is the 1st row of a new block
              Over (PARTITION BY code
                    ORDER BY date2 DESC) = block 
         THEN 0 
         ELSE 1 
      END AS flag
   FROM DATA
 ) AS dt

【讨论】:

  • 哇...它的工作原理!谢谢,我是窗口功能的新手,但它似乎是最好的解决方案。谢谢。
猜你喜欢
  • 2019-03-13
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 2017-11-04
相关资源
最近更新 更多