Postgresql 计算离散值的连续出现次数

Postgresql 计算离散值的连续出现次数,postgresql,gaps-and-islands,Postgresql,Gaps And Islands,我有下表,我想计算每个名字和每个标志的连续天数 Name Date Flag ------------------------------------- Alberta 01-01-2018 B Alberta 02-01-2018 B Alberta 03-01-2018 B Alberta 04-01-2018 L Alberta 05-01-2018 L

我有下表,我想计算每个名字和每个标志的连续天数

Name        Date            Flag 
-------------------------------------
Alberta    01-01-2018       B

Alberta    02-01-2018       B

Alberta    03-01-2018       B

Alberta    04-01-2018       L

Alberta    05-01-2018       L

Ambelos    01-01-2018       B

Ambelos    02-01-2018       B

Ambelos    03-01-2018       L

Ambelos    04-01-2018       B
我想要下面的

Name          Date            Flag     CountDays 
----------------------------------------------------
Alberta      03-01-2018        B          3

Alberta      05-01-2018        L          2

Ambelos      02-01-2018        B          2

Ambelos      03-01-2018        L          1

Ambelos      04-01-2018        B          1
我怎样才能做到这一点呢?

你可以使用这种技术

PostgreSQL 9.6架构设置

CREATE TABLE t
    (Name varchar(7), dt timestamp, Flag varchar(1))
;

INSERT INTO t
    (Name, dt, Flag)
VALUES
    ('Alberta', '2018-01-01 00:00:00', 'B'),
    ('Alberta', '2018-02-01 00:00:00', 'B'),
    ('Alberta', '2018-03-01 00:00:00', 'B'),
    ('Alberta', '2018-04-01 00:00:00', 'L'),
    ('Alberta', '2018-05-01 00:00:00', 'L'),
    ('Ambelos', '2018-01-01 00:00:00', 'B'),
    ('Ambelos', '2018-02-01 00:00:00', 'B'),
    ('Ambelos', '2018-03-01 00:00:00', 'L'),
    ('Ambelos', '2018-04-01 00:00:00', 'B')
;
SELECT name, 
       Max(dt) AS "Date", 
       flag, 
       Count(*) As CountDays
FROM   (SELECT t.*, 
               row_number() 
                 over ( 
                   PARTITION BY name 
                   ORDER BY dt ) - row_number() 
                                     over ( 
                                       PARTITION BY name, flag 
                                       ORDER BY dt ) AS seq 
        FROM   t) s 
GROUP  BY name, 
          flag, 
          seq 
ORDER  BY name,"Date" 
|    name |                 Date | flag | countdays |
|---------|----------------------|------|-----------|
| Alberta | 2018-03-01T00:00:00Z |    B |         3 |
| Alberta | 2018-05-01T00:00:00Z |    L |         2 |
| Ambelos | 2018-02-01T00:00:00Z |    B |         2 |
| Ambelos | 2018-03-01T00:00:00Z |    L |         1 |
| Ambelos | 2018-04-01T00:00:00Z |    B |         1 |
查询1

CREATE TABLE t
    (Name varchar(7), dt timestamp, Flag varchar(1))
;

INSERT INTO t
    (Name, dt, Flag)
VALUES
    ('Alberta', '2018-01-01 00:00:00', 'B'),
    ('Alberta', '2018-02-01 00:00:00', 'B'),
    ('Alberta', '2018-03-01 00:00:00', 'B'),
    ('Alberta', '2018-04-01 00:00:00', 'L'),
    ('Alberta', '2018-05-01 00:00:00', 'L'),
    ('Ambelos', '2018-01-01 00:00:00', 'B'),
    ('Ambelos', '2018-02-01 00:00:00', 'B'),
    ('Ambelos', '2018-03-01 00:00:00', 'L'),
    ('Ambelos', '2018-04-01 00:00:00', 'B')
;
SELECT name, 
       Max(dt) AS "Date", 
       flag, 
       Count(*) As CountDays
FROM   (SELECT t.*, 
               row_number() 
                 over ( 
                   PARTITION BY name 
                   ORDER BY dt ) - row_number() 
                                     over ( 
                                       PARTITION BY name, flag 
                                       ORDER BY dt ) AS seq 
        FROM   t) s 
GROUP  BY name, 
          flag, 
          seq 
ORDER  BY name,"Date" 
|    name |                 Date | flag | countdays |
|---------|----------------------|------|-----------|
| Alberta | 2018-03-01T00:00:00Z |    B |         3 |
| Alberta | 2018-05-01T00:00:00Z |    L |         2 |
| Ambelos | 2018-02-01T00:00:00Z |    B |         2 |
| Ambelos | 2018-03-01T00:00:00Z |    L |         1 |
| Ambelos | 2018-04-01T00:00:00Z |    B |         1 |

CREATE TABLE t
    (Name varchar(7), dt timestamp, Flag varchar(1))
;

INSERT INTO t
    (Name, dt, Flag)
VALUES
    ('Alberta', '2018-01-01 00:00:00', 'B'),
    ('Alberta', '2018-02-01 00:00:00', 'B'),
    ('Alberta', '2018-03-01 00:00:00', 'B'),
    ('Alberta', '2018-04-01 00:00:00', 'L'),
    ('Alberta', '2018-05-01 00:00:00', 'L'),
    ('Ambelos', '2018-01-01 00:00:00', 'B'),
    ('Ambelos', '2018-02-01 00:00:00', 'B'),
    ('Ambelos', '2018-03-01 00:00:00', 'L'),
    ('Ambelos', '2018-04-01 00:00:00', 'B')
;
SELECT name, 
       Max(dt) AS "Date", 
       flag, 
       Count(*) As CountDays
FROM   (SELECT t.*, 
               row_number() 
                 over ( 
                   PARTITION BY name 
                   ORDER BY dt ) - row_number() 
                                     over ( 
                                       PARTITION BY name, flag 
                                       ORDER BY dt ) AS seq 
        FROM   t) s 
GROUP  BY name, 
          flag, 
          seq 
ORDER  BY name,"Date" 
|    name |                 Date | flag | countdays |
|---------|----------------------|------|-----------|
| Alberta | 2018-03-01T00:00:00Z |    B |         3 |
| Alberta | 2018-05-01T00:00:00Z |    L |         2 |
| Ambelos | 2018-02-01T00:00:00Z |    B |         2 |
| Ambelos | 2018-03-01T00:00:00Z |    L |         1 |
| Ambelos | 2018-04-01T00:00:00Z |    B |         1 |
你可以使用技术

PostgreSQL 9.6架构设置

CREATE TABLE t
    (Name varchar(7), dt timestamp, Flag varchar(1))
;

INSERT INTO t
    (Name, dt, Flag)
VALUES
    ('Alberta', '2018-01-01 00:00:00', 'B'),
    ('Alberta', '2018-02-01 00:00:00', 'B'),
    ('Alberta', '2018-03-01 00:00:00', 'B'),
    ('Alberta', '2018-04-01 00:00:00', 'L'),
    ('Alberta', '2018-05-01 00:00:00', 'L'),
    ('Ambelos', '2018-01-01 00:00:00', 'B'),
    ('Ambelos', '2018-02-01 00:00:00', 'B'),
    ('Ambelos', '2018-03-01 00:00:00', 'L'),
    ('Ambelos', '2018-04-01 00:00:00', 'B')
;
SELECT name, 
       Max(dt) AS "Date", 
       flag, 
       Count(*) As CountDays
FROM   (SELECT t.*, 
               row_number() 
                 over ( 
                   PARTITION BY name 
                   ORDER BY dt ) - row_number() 
                                     over ( 
                                       PARTITION BY name, flag 
                                       ORDER BY dt ) AS seq 
        FROM   t) s 
GROUP  BY name, 
          flag, 
          seq 
ORDER  BY name,"Date" 
|    name |                 Date | flag | countdays |
|---------|----------------------|------|-----------|
| Alberta | 2018-03-01T00:00:00Z |    B |         3 |
| Alberta | 2018-05-01T00:00:00Z |    L |         2 |
| Ambelos | 2018-02-01T00:00:00Z |    B |         2 |
| Ambelos | 2018-03-01T00:00:00Z |    L |         1 |
| Ambelos | 2018-04-01T00:00:00Z |    B |         1 |
查询1

CREATE TABLE t
    (Name varchar(7), dt timestamp, Flag varchar(1))
;

INSERT INTO t
    (Name, dt, Flag)
VALUES
    ('Alberta', '2018-01-01 00:00:00', 'B'),
    ('Alberta', '2018-02-01 00:00:00', 'B'),
    ('Alberta', '2018-03-01 00:00:00', 'B'),
    ('Alberta', '2018-04-01 00:00:00', 'L'),
    ('Alberta', '2018-05-01 00:00:00', 'L'),
    ('Ambelos', '2018-01-01 00:00:00', 'B'),
    ('Ambelos', '2018-02-01 00:00:00', 'B'),
    ('Ambelos', '2018-03-01 00:00:00', 'L'),
    ('Ambelos', '2018-04-01 00:00:00', 'B')
;
SELECT name, 
       Max(dt) AS "Date", 
       flag, 
       Count(*) As CountDays
FROM   (SELECT t.*, 
               row_number() 
                 over ( 
                   PARTITION BY name 
                   ORDER BY dt ) - row_number() 
                                     over ( 
                                       PARTITION BY name, flag 
                                       ORDER BY dt ) AS seq 
        FROM   t) s 
GROUP  BY name, 
          flag, 
          seq 
ORDER  BY name,"Date" 
|    name |                 Date | flag | countdays |
|---------|----------------------|------|-----------|
| Alberta | 2018-03-01T00:00:00Z |    B |         3 |
| Alberta | 2018-05-01T00:00:00Z |    L |         2 |
| Ambelos | 2018-02-01T00:00:00Z |    B |         2 |
| Ambelos | 2018-03-01T00:00:00Z |    L |         1 |
| Ambelos | 2018-04-01T00:00:00Z |    B |         1 |

CREATE TABLE t
    (Name varchar(7), dt timestamp, Flag varchar(1))
;

INSERT INTO t
    (Name, dt, Flag)
VALUES
    ('Alberta', '2018-01-01 00:00:00', 'B'),
    ('Alberta', '2018-02-01 00:00:00', 'B'),
    ('Alberta', '2018-03-01 00:00:00', 'B'),
    ('Alberta', '2018-04-01 00:00:00', 'L'),
    ('Alberta', '2018-05-01 00:00:00', 'L'),
    ('Ambelos', '2018-01-01 00:00:00', 'B'),
    ('Ambelos', '2018-02-01 00:00:00', 'B'),
    ('Ambelos', '2018-03-01 00:00:00', 'L'),
    ('Ambelos', '2018-04-01 00:00:00', 'B')
;
SELECT name, 
       Max(dt) AS "Date", 
       flag, 
       Count(*) As CountDays
FROM   (SELECT t.*, 
               row_number() 
                 over ( 
                   PARTITION BY name 
                   ORDER BY dt ) - row_number() 
                                     over ( 
                                       PARTITION BY name, flag 
                                       ORDER BY dt ) AS seq 
        FROM   t) s 
GROUP  BY name, 
          flag, 
          seq 
ORDER  BY name,"Date" 
|    name |                 Date | flag | countdays |
|---------|----------------------|------|-----------|
| Alberta | 2018-03-01T00:00:00Z |    B |         3 |
| Alberta | 2018-05-01T00:00:00Z |    L |         2 |
| Ambelos | 2018-02-01T00:00:00Z |    B |         2 |
| Ambelos | 2018-03-01T00:00:00Z |    L |         1 |
| Ambelos | 2018-04-01T00:00:00Z |    B |         1 |

对于相同的名称和标志,可以有两个或更多的天数序列?例如,从1月1日到3日-第一个序列和从5日到08年1月-第二个序列,结果表中将有两行相同的名称和标志。是的,如果我理解您的意思,可能会发生这种情况。请检查我的答案,如果答案对您有效,请接受。请阅读:了解为什么它很重要。对于相同的名称和标志,可以是2天或更长的时间序列?例如,从1月1日到3日-第一个序列和从5日到08年1月-第二个序列,结果表中将有两行相同的名称和标志。是的,如果我理解您的意思,可能会发生这种情况。请检查我的答案,如果答案对您有效,请接受。请阅读:来理解为什么它很重要。@VanessaZorgia:不客气。请读:@VanessaZorgia:不客气。请阅读: