用于检测日期序列中间隙的SQL Server逻辑

时间:2015-10-28 06:55:12

标签: sql-server-2008 date while-loop sequence common-table-expression

我有下表:

     Plan     Start Date     End Date     Order    
    ------------------------------------------
      1    1st Jan, 2014  31st Jan, 2014   1
      1    1st Feb, 2014  24th Feb, 2014   2
      1   25th Feb, 2014  30th Jun, 2014   3
      1    7th Jul, 2014  28th Aug, 2014   4
      1    1st Sep, 2014  30th Sep, 2014   5
      1    1st Oct, 2014  31st Dec, 2014   6

从上面的数据可以看出,对于计划1,订单1,2,3是连续的,那么我们有一个缺口,然后是4阶,然后再是间隙,然后订单5,6是连续的。对于计划1,我想将覆盖范围捆绑如下:(1,2,3),(4),(5,6),预期结果集应如下:

     Plan     Start Date     End Date         
    -------------------------------------
      1    1st Jan, 2014  30th Jun, 2014 
      1    7th Jul, 2014  28th Aug, 2014 
      1    1st Sep, 2014  31st Dec, 2014

我使用了一个基本的while循环迭代逻辑来实现我想要的输出。但是,当存在大量记录(比如100万)时,while循环逻辑的性能受到重大影响(因为它是行式操作)。我试着提出一种基于递归CTE的方法,但无法得到理想的结果。在这种情况下,任何可以使用批处理逻辑的输入都非常有用。

2 个答案:

答案 0 :(得分:0)

WHERE中的子查询过滤掉连续的行。 SELECT中的子查询将找到日期范围结束。

数据:

CREATE TABLE #tab([Plan] INT, StartDate DATE, EndDate DATE, [Order] INT )

INSERT INTO #tab VALUES
(1, '2014-01-01', '2014-01-31', 1),(1, '2014-02-01', '2014-02-24', 2),
(1, '2014-02-25', '2014-06-30', 3),(1, '2014-07-07', '2014-08-28', 4),
(1, '2014-09-01', '2014-09-30', 5),(1, '2014-10-01', '2014-12-31', 6);

查询:

SELECT [Plan],D.StartDate, 
   [EndDate] = (SELECT MIN(E.EndDate)
                FROM #tab E
                WHERE E.EndDate >= D.EndDate
                 AND E.[Plan] = D.[Plan]
                 AND NOT EXISTS (SELECT 1
                                 FROM #tab E2
                                 WHERE DATEADD(d,1,E.StartDate) < E2.StartDate
                                   AND DATEADD(d,1,E.EndDate) >= E2.StartDate
                                   AND E.[Plan] = E2.[Plan]))
FROM #tab D
WHERE NOT EXISTS (SELECT 1
                  FROM #tab D2
                  WHERE D.StartDate <= DATEADD(d, 1,D2.EndDate)
                    AND D.EndDate > D2.EndDate
                    AND D.[Plan] = D2.[Plan])
ORDER BY [Plan], StartDate;

LiveDemo

输出:

╔══════╦═════════════════════╦═════════════════════╗
║ Plan ║      StartDate      ║       EndDate       ║
╠══════╬═════════════════════╬═════════════════════╣
║    1 ║ 2014-01-01 00:00:00 ║ 2014-06-30 00:00:00 ║
║    1 ║ 2014-07-07 00:00:00 ║ 2014-08-28 00:00:00 ║
║    1 ║ 2014-09-01 00:00:00 ║ 2014-12-31 00:00:00 ║
╚══════╩═════════════════════╩═════════════════════╝

答案 1 :(得分:0)

查看其他查询

;(function(){
    var app = angular.module('myawesomeapp',[])
    .directive('restrictInput', [function(){

        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                var ele = element[0];
                var regex = RegExp(attrs.restrictInput);
                var value = ele.value;

                ele.addEventListener('keyup',function(e){
                    if (regex.test(ele.value)){
                        value = ele.value;
                    }else{
                        ele.value = value;
                    }
                });
            }
        };
    }]);    
}());