sql - 使用 RANK() OVER 计数时跳过空值

标签 sql sql-server tsql

给定一组行,有时带有一个字段 null有时不是:

SELECT 
   Date, TheThing
FROM MyData
ORDER BY Date


Date                     TheThing
-----------------------  --------
2016-03-09 08:17:29.867  a
2016-03-09 08:18:33.327  a
2016-03-09 14:32:01.240  NULL
2016-10-21 19:53:49.983  NULL
2016-11-12 03:25:21.753  b
2016-11-24 07:43:24.483  NULL
2016-11-28 16:06:23.090  b
2016-11-28 16:09:07.200  c
2016-12-10 11:21:55.807  c

我想要一个计算非空值的排名列:
Date                     TheThing  DesiredTotal
-----------------------  --------  ------------
2016-03-09 08:17:29.867  a         1
2016-03-09 08:18:33.327  a         2
2016-03-09 14:32:01.240  NULL      2 <---notice it's still 2 (good)
2016-10-21 19:53:49.983  NULL      2 <---notice it's still 2 (good)
2016-11-12 03:25:21.753  b         3
2016-11-24 07:43:24.483  NULL      3 <---notice it's still 3 (good)
2016-11-28 16:06:23.090  b         4
2016-11-28 16:09:07.200  c         5
2016-12-10 11:21:55.807  c         6

我尝试显而易见的:
SELECT 
   Date, TheThing, 
   RANK() OVER(ORDER BY Date) AS Total
FROM MyData
ORDER BY Date

但是RANK()计数空值:
Date                     TheThing  Total
-----------------------  --------  -----
2016-03-09 08:17:29.867  a         1
2016-03-09 08:18:33.327  a         2
2016-03-09 14:32:01.240  NULL      3 <--- notice it is 3 (bad)
2016-10-21 19:53:49.983  NULL      4 <--- notice it is 4 (bad)
2016-11-12 03:25:21.753  b         5 <--- and all the rest are wrong (bad)
2016-11-24 07:43:24.483  NULL      7
2016-11-28 16:06:23.090  b         8
2016-11-28 16:09:07.200  c         9
2016-12-10 11:21:55.807  c         10

如何指导RANK() (或 DENSE_RANK() )不计算空值?

您是否尝试过使用分区?

为什么是!更糟糕:
SELECT 
   Date, TheThing, 
   RANK() OVER(PARTITION BY(CASE WHEN TheThing IS NOT NULL THEN 1 ELSE 0 END) ORDER BY Date) AS Total
FROM MyData
ORDER BY Date

但是RANK()计数空值:
Date                     TheThing  Total
-----------------------  --------  -----
2016-03-09 08:17:29.867  a         1
2016-03-09 08:18:33.327  a         2
2016-03-09 14:32:01.240  NULL      1 <--- reset to 1?
2016-10-21 19:53:49.983  NULL      2 <--- why go up?
2016-11-12 03:25:21.753  b         3 
2016-11-24 07:43:24.483  NULL      3 <--- didn't reset?
2016-11-28 16:06:23.090  b         4 
2016-11-28 16:09:07.200  c         5
2016-12-10 11:21:55.807  c         6

现在我随机输入东西 - 疯狂的挥舞。
SELECT 
   Date, TheThing, 
   RANK() OVER(PARTITION BY(CASE WHEN TheThing IS NOT NULL THEN 1 ELSE NULL END) ORDER BY Date) AS Total
FROM MyData
ORDER BY Date

SELECT 
   Date, TheThing, 
   DENSE_RANK() OVER(PARTITION BY(CASE WHEN TheThing IS NOT NULL THEN 1 ELSE NULL END) ORDER BY Date) AS Total
FROM MyData
ORDER BY Date

编辑 : 有了所有的答案,我花了很多次迭代才找到我 的所有边缘情况。不要想。最后我概念上想要的是 OVER()为了计数。我不知道 OVER适用于除 RANK 以外的任何内容(和 DENSE_RANK )。

http://sqlfiddle.com/#!18/c6d87/1

奖励阅读
  • How to use RANK() in SQL Server
  • RANK without counting nulls
  • SQL Server 2012 PERCENT_RANK() Exclude NULLS
  • Exclude null values using DENSE_RANK
  • 最佳答案

    我认为您正在寻找累积计数:

    SELECT Date, TheThing, 
           COUNT(theThing) OVER (ORDER BY Date) AS Total
    FROM MyData
    ORDER BY Date;
    

    关于sql - 使用 RANK() OVER 计数时跳过空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51827711/

    相关文章:

    mysql - SQL日期/时间字段查询

    sql - 使用 GroupBy 从多对多中选择

    mysql - 添加正确的 MySQL 触发器

    sql - 如何在 SQL Server 2008 中重建 View

    sql - 复制父子属性

    sql - 在 SQL Server 中的另一个存储过程中执行一个存储过程

    sql-server - 为什么使用 NEWID() 比 NEWSEQUENTIALID() 使用更多空间?

    sql-server - MVC 3 : The MSDTC transaction manager was unable to pull the transaction from the source

    sql-server - 将一列相加并减去第二列

    sql-server - 我可以稍后在同一 View 中使用在 SQL Server View 中计算的列吗?