SQL按连续行的会话对行进行排序

时间:2018-11-01 10:00:50

标签: sql postgresql window-functions

我有一张桌子:

 id |   emp_id   |    telecom_id    |
----+------------+------------------+
  1 | 1          | 1                |
  2 | 1          | 1                |
  3 | 1          | 1                |
  4 | 1          | 2                |
  5 | 1          | 3                |
  6 | 1          | 3                |
  7 | 1          | 1                |
  8 | 2          | 5                |
  9 | 2          | 1                |
 10 | 1          | 1                |
 11 | 2          | 1                |
 12 | 2          | 1                |

为方便起见,以下是用于创建和填充表的命令:

CREATE TABLE table1 (
        id int NOT NULL,
        emp_id varchar(255),
        telecom_id varchar(255)
    );

    insert into table1 (id, emp_id, telecom_id) values(1, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(2, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(3, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(4, '1', '2');
    insert into table1 (id, emp_id, telecom_id) values(5, '1', '3');
    insert into table1 (id, emp_id, telecom_id) values(6, '1', '3');
    insert into table1 (id, emp_id, telecom_id) values(7, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(8, '2', '5');
    insert into table1 (id, emp_id, telecom_id) values(9, '2', '1');
    insert into table1 (id, emp_id, telecom_id) values(10, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(11, '2', '1');
    insert into table1 (id, emp_id, telecom_id) values(12, '2', '1');

我需要以这种方式对表中的行进行排名,即每个会话行的排名都相同。会话是一系列连续的行,它们的emp_id和telecom_id相等。

例如,第1-3行构成一个会话,因为所有3行的emp_id = 1telecom_id = 1。第4行构成另一个会话。第5-6行构成了第三届会议等。

使用至关重要的方法来排序表中数据的存储顺序。

所需的输出:

 id |   emp_id   |    telecom_id    | rnk
----+------------+------------------+------
  1 | 1          | 1                | 1
  2 | 1          | 1                | 1
  3 | 1          | 1                | 1
  4 | 1          | 2                | 2
  5 | 1          | 3                | 3
  6 | 1          | 3                | 3
  7 | 1          | 1                | 4
  8 | 2          | 5                | 5
  9 | 2          | 1                | 6
 10 | 1          | 1                | 7
 11 | 2          | 1                | 8
 12 | 2          | 1                | 8

我尝试了各种带有窗口功能的选项,但没有一个能按预期方式工作。 这是产生与我要达到的结果最接近的结果的尝试:

select emp_id, telecom_id, rank() 
over(partition by emp_id, telecom_id order by id) as rnk
from table1;

我正在使用PostgreSQL。

1 个答案:

答案 0 :(得分:4)

您可以尝试使用lag窗口函数获取pre-Val并将条件聚合函数SUM与窗口函数结合使用来构成逻辑。

CREATE TABLE table1 (
        id int NOT NULL,
        emp_id varchar(255),
        telecom_id varchar(255)
    );

    insert into table1 (id, emp_id, telecom_id) values(1, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(2, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(3, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(4, '1', '2');
    insert into table1 (id, emp_id, telecom_id) values(5, '1', '3');
    insert into table1 (id, emp_id, telecom_id) values(6, '1', '3');
    insert into table1 (id, emp_id, telecom_id) values(7, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(8, '2', '5');
    insert into table1 (id, emp_id, telecom_id) values(9, '2', '1');
    insert into table1 (id, emp_id, telecom_id) values(10, '1', '1');
    insert into table1 (id, emp_id, telecom_id) values(11, '2', '1');
    insert into table1 (id, emp_id, telecom_id) values(12, '2', '1');

查询1

SELECT id,emp_id,telecom_id,
       SUM(CASE WHEN 
            pretelecomVal = telecom_id 
            and pre_emp_idVal = emp_id 
           then 0 else 1 end) over(order by id) rnk
FROM (
  select *,
         lag(telecom_id) over(partition by emp_id order by id) pretelecomVal,
         lag(emp_id) over(order by id) pre_emp_idVal
  from table1
) t1

Results

| id | emp_id | telecom_id | rnk |
|----|--------|------------|-----|
|  1 |      1 |          1 |   1 |
|  2 |      1 |          1 |   1 |
|  3 |      1 |          1 |   1 |
|  4 |      1 |          2 |   2 |
|  5 |      1 |          3 |   3 |
|  6 |      1 |          3 |   3 |
|  7 |      1 |          1 |   4 |
|  8 |      2 |          5 |   5 |
|  9 |      2 |          1 |   6 |
| 10 |      1 |          1 |   7 |
| 11 |      2 |          1 |   8 |
| 12 |      2 |          1 |   8 |