在SQL Server 2012中选择连续ID

时间:2017-02-16 05:30:29

标签: sql sql-server-2012

我有一张这样的桌子。

ID              Installment ID       DateDue 
------------------------------------------------------------    
000000000008    29                   2017-03-15 00:00:00.000 
000000000008    30                   2017-04-15 00:00:00.000 
000000000008    32                   2017-06-15 00:00:00.000 
000000000008    33                   2017-07-15 00:00:00.000 
000000000008    34                   2017-08-15 00:00:00.000

我需要的是一个select查询,该查询仅在特定日期范围之间的3个成功连续分期(在此示例中为32,33,34)返回数据。

假设失败则填入另一个表(31)。

所以我希望返回序列号,分期付款ID。

2 个答案:

答案 0 :(得分:0)

您可以使用SqlServer 2012中提供的LEADLAG功能并执行此操作。

Demo here

;WITH cte1 AS
(
SELECT * , datepart(m,(lead(datedue) OVER(ORDER BY installmentid)))-DATEPART(m,datedue) nowtonext
         ,DATEPART(m,datedue)-datepart(m,(lag(datedue) OVER(ORDER BY installmentid))) prevtonow
         ,ROW_NUMBER() OVER(ORDER BY installmentid) as rn
FROM YourTable
),
cte2 AS
(
SELECT rn,id,installmentid,datedue,nowtonext,prevtonow
        ,lead(prevtonow) OVER(ORDER BY rn) AS prev
        ,lag(nowtonext) OVER(ORDER BY rn) AS nxt
FROM cte1
)

SELECT id,installmentid,datedue 
FROM cte1 
WHERE rn BETWEEN (SELECT rn-1 FROM cte2 WHERE nowtonext = 1 AND prevtonow=1 AND prev=1 AND nxt=1)
            and (SELECT rn+1 FROM cte2 WHERE nowtonext = 1 AND prevtonow=1 AND prev=1 AND nxt=1)

答案 1 :(得分:0)

您可以使用以下查询来返回连续InstallmentID个连续记录的岛屿:

;WITH CTE_Group AS (
   SELECT ID,
          InstallmentID,
          DateDue,
          ROW_NUMBER() OVER (PARTITION BY ID 
                             ORDER BY DateDue) - InstallmentID AS grp
   FROM mytable
   WHERE DateDue BETWEEN @startDate AND @endDate
), CTE_Count AS (
   SELECT ID, InstallmentID, DateDue,
          COUNT(*) OVER (PARTITION BY ID, grp) AS cnt
   FROM CTE_Group
)
SELECT ID, InstallmentID, DateDue
FROM CTE_Count
WHERE cnt >= 3

如果您只希望每个岛屿中有3条记录,那么您可以使用ROW_NUMBERPARTITION BY cnt子句来提取该岛的前3条记录。

说明:第一个CTE CTE_Group的查询使用了行号技巧'之间的差异。为了识别在预定义的日期范围(InstallmentID)内具有连续@startDate - @endDate个数字的连续记录。

来自CTE_Group 的输出:

ID  InstallmentID   DateDue     grp
------------------------------------
8   29              2017-03-15  -28
8   30              2017-04-15  -28
8   32              2017-06-15  -29
8   33              2017-07-15  -29
8   34              2017-08-15  -29

第二个CTE的查询CTE_Count使用COUNT() OVER()来计算每个岛屿的人口。

来自CTE_Count 的输出:

ID  InstallmentID   DateDue     Cnt
-----------------------------------
8   32              2017-06-15  3
8   33              2017-07-15  3
8   34              2017-08-15  3
8   29              2017-03-15  2
8   30              2017-04-15  2

使用CTE_Count,我们可以轻松过滤掉属于人口2或更少的岛屿的记录。

Demo here