sql - 基于条件的数量

标签 sql sql-server tsql gaps-and-islands

我正在尝试根据条件生成一个数字。 当按 Start_Date 排序的 Client 分区中的“Stop”列中有 yes 时,Dense Rank 必须重新开始。所以我尝试了几件事,但它仍然不是我想要的。 我的表格有当前号码和预期号码

+-----------+------------+------+------------+-------------+
| Client_No | Start_Date | Stop | Current_No | Expected_No |
+-----------+------------+------+------------+-------------+
|     1     |  1-1-2018  |  No  |      1     |      1      |
+-----------+------------+------+------------+-------------+
|     1     |  1-2-2018  |  No  |      2     |      2      |
+-----------+------------+------+------------+-------------+
|     1     |  1-3-2018  |  No  |      3     |      3      |
+-----------+------------+------+------------+-------------+
|     1     |  1-4-2018  |  Yes |      1     |      1      |
+-----------+------------+------+------------+-------------+
|     1     |  1-5-2018  |  No  |      4     |      2      |
+-----------+------------+------+------------+-------------+
|     1     |  1-6-2018  |  No  |      5     |      3      |
+-----------+------------+------+------------+-------------+
|     2     |  1-2-2018  |  No  |      1     |      1      |
+-----------+------------+------+------------+-------------+
|     2     |  1-3-2018  |  No  |      2     |      2      |
+-----------+------------+------+------------+-------------+
|     2     |  1-4-2018  |  Yes |      1     |      1      |
+-----------+------------+------+------------+-------------+
|     2     |  1-5-2018  |  No  |      3     |      2      |
+-----------+------------+------+------------+-------------+
|     2     |  1-6-2018  |  Yes |      2     |      1      |
+-----------+------------+------+------------+-------------+

到目前为止我使用的查询:

DENSE_RANK() OVER(PARTITION BY Client_No, Stop ORDER BY Start_Date ASC)

这似乎不是解决方案,因为它从值“否”算起,但我不知道如何用另一种方式处理这个问题。

最佳答案

解决此类 Gaps-And-Islands 难题的一种方法是首先计算以"is"停止的排名。

然后在该等级上计算 row_number 或 dense_rank。

例如:

create table test 
(
  Id int identity(1,1) primary key,
  Client_No int,
  Start_Date date,
  Stop varchar(3)
)
insert into test 
(Client_No, Start_Date, Stop) values
  (1,'2018-01-01','No')
 ,(1,'2018-02-01','No')
 ,(1,'2018-03-01','No')
 ,(1,'2018-04-01','Yes')
 ,(1,'2018-05-01','No')
 ,(1,'2018-06-01','No')

 ,(2,'2018-02-01','No')
 ,(2,'2018-03-01','No')
 ,(2,'2018-04-01','Yes')
 ,(2,'2018-05-01','No')
 ,(2,'2018-06-01','Yes')
select *
, row_number() over (partition by Client_no, Rnk order by start_date) as rn
from
(
  select *
  , sum(case when Stop = 'Yes' then 1 else 0 end) over (partition by Client_No order by start_date) rnk
  from test
) q
order by Client_No, start_date
GO
Id | Client_No | Start_Date          | Stop | rnk | rn
-: | --------: | :------------------ | :--- | --: | :-
 1 |         1 | 01/01/2018 00:00:00 | No   |   0 | 1 
 2 |         1 | 01/02/2018 00:00:00 | No   |   0 | 2 
 3 |         1 | 01/03/2018 00:00:00 | No   |   0 | 3 
 4 |         1 | 01/04/2018 00:00:00 | Yes  |   1 | 1 
 5 |         1 | 01/05/2018 00:00:00 | No   |   1 | 2 
 6 |         1 | 01/06/2018 00:00:00 | No   |   1 | 3 
 7 |         2 | 01/02/2018 00:00:00 | No   |   0 | 1 
 8 |         2 | 01/03/2018 00:00:00 | No   |   0 | 2 
 9 |         2 | 01/04/2018 00:00:00 | Yes  |   1 | 1 
10 |         2 | 01/05/2018 00:00:00 | No   |   1 | 2 
11 |         2 | 01/06/2018 00:00:00 | Yes  |   2 | 1 

db<> fiddle here

使用这个的区别:

row_number() over (partition by Client_no, Rnk order by start_date)

与此相对:

dense_rank() over (partition by Client_no, Rnk order by start_date)

dense_rank 会为每个 Client_no 和 Rnk 的相同开始日期计算相同的数字。

关于sql - 基于条件的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59292274/

相关文章:

MySQL 查询返回意外值

sql-server - 如果里面的字符串比最大长度短,一个 nvarchar 列占用多少磁盘空间

sql-server - Service Broker 两端的 session 句柄是否应该相同?

sql - 在不使用 MAX、AVG 等聚合函数的情况下,将行转换为 SQL 中的列

sql - Varchar(Max) 在 Exec 中不起作用

sql - 如何确定哪些字符串或二进制数据将被截断?

MySQL。如何通过多列进行选择

mysql - 引用表和引用表

mysql - 如何根据条件检索所有记录

sql-server - 日期转换和文化 : Difference between DATE and DATETIME