对连续的空值进行排序
Rank consecutive null values
我想对我的记录的连续空值进行排名。每条记录都会排名为1。对于只出现一次的空值,排名也为1。但是对于连续出现的空值,第一条记录排名为1,第二条记录排名为2记录等。这是我的代码。
CREATE TABLE #my_table
(
id BIGINT IDENTITY PRIMARY KEY
,fruit varchar(100)
);
INSERT INTO #my_table
SELECT 'apple'
UNION ALL SELECT 'apple'
UNION ALL SELECT NULL
UNION ALL SELECT 'pineapple'
UNION ALL SELECT 'banana'
UNION ALL SELECT NULL
UNION ALL SELECT NULL
UNION ALL SELECT 'orange'
select * from #my_table
预期结果
+----+-----------+------+
| id | fruit | rank |
+----+-----------+------+
| 1 | apple | 1 |
| 2 | apple | 1 |
| 3 | NULL | 1 |
| 4 | pineapple | 1 |
| 5 | banana | 1 |
| 6 | NULL | 1 |
| 7 | NULL | 2 |
| 8 | orange | 1 |
+----+-----------+------+
如何查询?
请帮忙!
您可以使用 ROW_NUMBER
的差异来获得连续 NULL
值的分组:
WITH Cte AS(
SELECT *,
g = ROW_NUMBER() OVER(ORDER BY id)
- ROW_NUMBER() OVER(PARTITION BY fruit ORDER BY id)
FROM #my_table
)
SELECT
id,
fruit,
CASE
WHEN fruit IS NULL THEN ROW_NUMBER() OVER(PARTITION BY fruit, g ORDER BY id)
ELSE 1
END AS rank
FROM Cte
ORDER BY id;
CREATE TABLE #my_table
(
id BIGINT IDENTITY PRIMARY KEY
,fruit varchar(100)
);
INSERT INTO #my_table
SELECT 'apple'
UNION ALL SELECT 'apple'
UNION ALL SELECT NULL
UNION ALL SELECT 'pineapple'
UNION ALL SELECT 'banana'
UNION ALL SELECT NULL
UNION ALL SELECT NULL
UNION ALL SELECT 'orange'
;
WITH REC_CTE (id,fruit,ranks)
AS (
-- Anchor definition
SELECT id,
fruit,
1 as ranks
FROM #my_table
WHERE fruit is not null
-- Recursive definition
UNION ALL
SELECT son.id,
son.fruit,
case when son.fruit is null AND father.fruit is null then
father.ranks + 1
else
1
end as ranks
FROM #my_table son INNER JOIN
REC_CTE father
on son.id = father.id +1
WHERE son.fruit is null
--AND father.fruit is null
)
SELECT * from REC_CTE order by id
DROP TABLE #my_table
以下解决方案不使用递归(限于 32767 级 = ~ 行,具体取决于解决方案)并且它仅使用两个 agregate/ranking 函数(SUM
和 DENSE_RANK
):
;WITH Base
AS (
SELECT *, IIF(fruit IS NULL, SUM(IIF(fruit IS NOT NULL, 1, 0)) OVER(ORDER BY id), NULL) AS group_num
FROM @my_table t
)
SELECT *, IIF(fruit IS NULL, DENSE_RANK() OVER(PARTITION BY group_num ORDER BY id), 1) rnk
FROM Base b
ORDER BY id
结果:
id fruit group_num rnk
--- --------- --------- ---
100 apple NULL 1
125 apple NULL 1
150 NULL 2 1
175 pineapple NULL 1
200 banana NULL 1
225 NULL 4 1
250 NULL 4 2
275 orange NULL 1
300 NULL 5 1
325 NULL 5 2
350 NULL 5 3
我想对我的记录的连续空值进行排名。每条记录都会排名为1。对于只出现一次的空值,排名也为1。但是对于连续出现的空值,第一条记录排名为1,第二条记录排名为2记录等。这是我的代码。
CREATE TABLE #my_table
(
id BIGINT IDENTITY PRIMARY KEY
,fruit varchar(100)
);
INSERT INTO #my_table
SELECT 'apple'
UNION ALL SELECT 'apple'
UNION ALL SELECT NULL
UNION ALL SELECT 'pineapple'
UNION ALL SELECT 'banana'
UNION ALL SELECT NULL
UNION ALL SELECT NULL
UNION ALL SELECT 'orange'
select * from #my_table
预期结果
+----+-----------+------+
| id | fruit | rank |
+----+-----------+------+
| 1 | apple | 1 |
| 2 | apple | 1 |
| 3 | NULL | 1 |
| 4 | pineapple | 1 |
| 5 | banana | 1 |
| 6 | NULL | 1 |
| 7 | NULL | 2 |
| 8 | orange | 1 |
+----+-----------+------+
如何查询?
请帮忙!
您可以使用 ROW_NUMBER
的差异来获得连续 NULL
值的分组:
WITH Cte AS(
SELECT *,
g = ROW_NUMBER() OVER(ORDER BY id)
- ROW_NUMBER() OVER(PARTITION BY fruit ORDER BY id)
FROM #my_table
)
SELECT
id,
fruit,
CASE
WHEN fruit IS NULL THEN ROW_NUMBER() OVER(PARTITION BY fruit, g ORDER BY id)
ELSE 1
END AS rank
FROM Cte
ORDER BY id;
CREATE TABLE #my_table
(
id BIGINT IDENTITY PRIMARY KEY
,fruit varchar(100)
);
INSERT INTO #my_table
SELECT 'apple'
UNION ALL SELECT 'apple'
UNION ALL SELECT NULL
UNION ALL SELECT 'pineapple'
UNION ALL SELECT 'banana'
UNION ALL SELECT NULL
UNION ALL SELECT NULL
UNION ALL SELECT 'orange'
;
WITH REC_CTE (id,fruit,ranks)
AS (
-- Anchor definition
SELECT id,
fruit,
1 as ranks
FROM #my_table
WHERE fruit is not null
-- Recursive definition
UNION ALL
SELECT son.id,
son.fruit,
case when son.fruit is null AND father.fruit is null then
father.ranks + 1
else
1
end as ranks
FROM #my_table son INNER JOIN
REC_CTE father
on son.id = father.id +1
WHERE son.fruit is null
--AND father.fruit is null
)
SELECT * from REC_CTE order by id
DROP TABLE #my_table
以下解决方案不使用递归(限于 32767 级 = ~ 行,具体取决于解决方案)并且它仅使用两个 agregate/ranking 函数(SUM
和 DENSE_RANK
):
;WITH Base
AS (
SELECT *, IIF(fruit IS NULL, SUM(IIF(fruit IS NOT NULL, 1, 0)) OVER(ORDER BY id), NULL) AS group_num
FROM @my_table t
)
SELECT *, IIF(fruit IS NULL, DENSE_RANK() OVER(PARTITION BY group_num ORDER BY id), 1) rnk
FROM Base b
ORDER BY id
结果:
id fruit group_num rnk
--- --------- --------- ---
100 apple NULL 1
125 apple NULL 1
150 NULL 2 1
175 pineapple NULL 1
200 banana NULL 1
225 NULL 4 1
250 NULL 4 2
275 orange NULL 1
300 NULL 5 1
325 NULL 5 2
350 NULL 5 3