根据条件将等级分配给记录

时间:2016-02-25 14:07:12

标签: sql postgresql

我有一张包含以下记录的表格:

=======================
| ID    |  device_num |
=======================
|  1    |      11     |
|  2    |      11     | 
|  3    |      NULL   |
|  4    |      11     |
|  5    |      11     |
|  6    |      NULL   |
|  7    |      11     |
|  8    |      12     |
|  9    |      12     |
|  10   |      13     |
|  11   |      NULL   | 
|  12   |      13     |
|  13   |      13     |
|  14   |      13     |
|  15   |      14     |
|  16   |      14     |
=======================

我想根据以下情况为每个设备编号分配一个等级:

1- Rank应以1开头。

2-如果两个记录具有相同的设备编号,则应将每个记录与其先前的记录进行比较,然后为记录分配相同的等级。

3-不要为NULL条记录分配等级。如果我们在Null记录之后得到相同的设备号,那么等级应该增加一个。

4-如果设备编号与之前的记录不匹配,则将等级增加1。

期望的输出:

===============================
| ID    | RANK  |  device_num |
===============================
|  1    |  1    |      11     |
|  2    |  1    |      11     | 
|  3    |       |      NULL   |
|  4    |  2    |      11     |
|  5    |  2    |      11     |
|  6    |       |      NULL   |
|  7    |  3    |      11     |
|  8    |  4    |      12     |
|  9    |  4    |      12     |
|  10   |  5    |      13     |
|  11   |       |      NULL   | 
|  12   |  6    |      13     |
|  13   |  6    |      13     |
|  14   |  6    |      13     |
|  15   |  7    |      14     |
|  16   |  7    |      14     |
===============================

我尝试使用PostgreSQL排名函数denserank等但不能按此顺序分配排名。

2 个答案:

答案 0 :(得分:1)

试试这个:

SELECT id, device_num, 
       CASE 
         WHEN device_num IS NOT NULL 
         THEN DENSE_RANK() OVER (ORDER BY CASE 
                                            WHEN device_num IS NOT NULL
                                            THEN min_id 
                                          END) 
       END AS RANK
FROM (
  SELECT id, device_num, 
         MIN(id) OVER (PARTITION BY device_num, grp) AS min_id
  FROM (
  SELECT id, device_num,
         ROW_NUMBER() OVER (ORDER BY id) - 
         ROW_NUMBER() OVER (PARTITION BY CASE 
                                           WHEN device_num IS NULL THEN -1 
                                           ELSE device_num
                                         END
                            ORDER BY id) AS grp
  FROM mytable) AS t) AS s
ORDER BY id

我做出了以下假设:

  1. 表格中有一个自动增量id字段,用于指定行顺序。
  2. device_num字段属于integer类型,-1不是该字段的有效值。
  3. Demo here

答案 1 :(得分:1)

我写了这样一个查询:

;WITH t1 AS (
SELECT *
    , ROW_NUMBER() OVER (ORDER BY (SELECT null)) AS rn
FROM yourTable
) -- To add a row-number to yourTable
, t2 AS (
SELECT *
    , CASE 
        WHEN device_num IS NULL THEN 0
        WHEN ISNULL(LAG(device_num) OVER (ORDER BY rn), -1) <> ISNULL(device_num, -1) THEN 1 
        ELSE 0 
    END AS willChange
FROM t1
)
SELECT device_num
    , CASE 
        WHEN device_num IS NULL THEN null
        ELSE SUM(willChange) OVER (ORDER BY rn)
    END [RANK]
FROM t2;

编辑:使用ID:它可以是这样的:

;WITH t AS (
SELECT *
    , CASE 
        WHEN device_num IS NULL THEN 0
        WHEN ISNULL(LAG(device_num) OVER (ORDER BY ID), -1) <> ISNULL(device_num, -1) THEN 1 
        ELSE 0 
    END AS willChange
FROM yourTable
)
SELECT device_num
    , CASE 
        WHEN device_num IS NULL THEN null
        ELSE SUM(willChange) OVER (ORDER BY ID)
    END [RANK]
FROM t;