【问题标题】:T-SQL windowing functions - counting the gapsT-SQL 窗口函数 - 计算间隙
【发布时间】:2020-06-23 18:43:12
【问题描述】:

我想计算窗口 v 中的间隙(用 NULL 填充的列),但我不知道如何。

IF OBJECT_ID('tempdb..#X') IS NOT NULL DROP TABLE #X;

CREATE TABLE #X
(
    ID INT IDENTITY(1,1) PRIMARY KEY,
    v INT
);

INSERT INTO #X
    SELECT 121 UNION ALL SELECT NULL UNION ALL SELECT NULL 
    UNION ALL SELECT 312 UNION ALL SELECT NULL UNION ALL SELECT NULL UNION ALL SELECT NULL
    UNION ALL SELECT 123 UNION ALL SELECT NULL UNION ALL SELECT NULL 
    UNION ALL SELECT 415 UNION ALL SELECT 416 UNION ALL SELECT NULL UNION ALL SELECT NULL UNION ALL SELECT NULL
    UNION ALL SELECT 200;


SELECT 
    ID, v, s, n, m, x, c
FROM
    (SELECT 
         ID, v, 
         MAX(v) OVER (PARTITION BY c) s,
         ROW_NUMBER() OVER (PARTITION BY c ORDER BY ID DESC) n,
         ROW_NUMBER() OVER (PARTITION BY c ORDER BY ID) - 1 m,
         COUNT(CASE WHEN v IS NULL THEN 1 END) OVER (PARTITION BY c) x,
         c
     FROM
         (SELECT 
              ID, v,
              -- c =  COUNT(CASE WHEN v IS NULL THEN 1 END) OVER (ORDER BY ID)
              c = COUNT(v) OVER (ORDER BY ID)
          FROM 
              #X) a
    ) a
ORDER BY 
    ID;

计算 c 已接近,但它不适用于一行中的两个填充列。

谁能给个提示?


谢谢你们,这对我有用。

【问题讨论】:

  • 请显示您想要的结果集。

标签: sql sql-server tsql window-functions


【解决方案1】:
select *, case when v is null then count(null_grp_start) over (order by id) end null_grp_id
from   (select *,case when v is null and lag(v,1,1) over (order by id) is not null then 1 end as null_grp_start
        from   t
        ) t

-

+----+--------+----------+-------------+
| ID |   v    | null_grp | null_grp_id |
+----+--------+----------+-------------+
|  1 | 121    | (null)   | (null)      |
|  2 | (null) | 1        | 1           |
|  3 | (null) | (null)   | 1           |
|  4 | 312    | (null)   | (null)      |
|  5 | (null) | 1        | 2           |
|  6 | (null) | (null)   | 2           |
|  7 | (null) | (null)   | 2           |
|  8 | 123    | (null)   | (null)      |
|  9 | (null) | 1        | 3           |
| 10 | (null) | (null)   | 3           |
| 11 | 415    | (null)   | (null)      |
| 12 | 416    | (null)   | (null)      |
| 13 | (null) | 1        | 4           |
| 14 | (null) | (null)   | 4           |
| 15 | (null) | (null)   | 4           |
| 16 | 200    | (null)   | (null)      |
+----+--------+----------+-------------+

【讨论】:

  • @JohnyL - 在这里
  • 非常感谢! ?
【解决方案2】:

如果要枚举 NULL 的周期,可以使用累积计数来获取非空值,然后枚举它们:

select t.*,
       (case when v is null then dense_rank() over (partition by v order by null_grp)
        end) as newcolumn
from (select t.*,
             count(v) over (order by id) as null_grp
      from t
     ) t;

Here 是一个 dbfiddle。

【讨论】:

  • 修复后工作。
【解决方案3】:
declare @t table
(
    id int identity primary key clustered,
    val int
);


insert into @t(val)
values (null), (2), (3), (null), (5), (null), (null), (null), (9), (10), (null), (null), (null), (null), (15);


select *, case when first_value(val) over(order by id) is null then 1 else 0 end + case when val is null then sum(addme) over(order by id) end as null_group_ordinal
from
(
select *, case when lag(val) over(order by id) is null and val is not null then 1 else 0 end as addme
from @t
) as src;

【讨论】:

  • @DavidדודוMarkovitz 请原谅,您可以在这里发布您昨天的解决方案吗?你删除了它......?谢谢! ?
猜你喜欢
  • 2021-02-25
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 2018-04-29
  • 2016-10-23
  • 1970-01-01
相关资源
最近更新 更多