2017-02-24 31 views
3

我们有通过智能手机经过在场地信息,代理的应用程序。该应用程序是由多个客户端使用,并且每个人都可以决定他们要多少天前/后允许其代理查看,即:在SQL Server 2005 +,计算一个日期是否落在范围,同时排除某些平日

  1. customer1表允许代理只看到今天和明天

  2. 顾客2可以让他的代理人就可以提前回来两天,两天。

  3. Customer3让他的代理人看一眼星期返回并在一周前,总共15天(算上今天)。

目前最大可能设置为15天:-7天,今天+7天。

每个客户都有自己的用自己的DB和他自己的一套参数服务器。

给定一个日期范围(我们只是把所有的2017年):

DECLARE @TABLE TABLE 
(
    RowID INT IDENTITY 
    ,Stamp DATETIME --Remember, I'm in 2005 and don't have the DATE type 
) 
; 

WITH CTE AS 
(
    SELECT CONVERT(DATETIME,'01/01/2017',101) AS Stamp 
     UNION ALL 
    SELECT DATEADD(DAY,1,X.Stamp) 
    FROM CTE AS X 
    WHERE X.Stamp < '12/31/2017' 
) 
INSERT INTO @TABLE (Stamp) 
SELECT Stamp FROM CTE OPTION (MaxRecursion 365) 
; 

并给予三个参数 - 今天的日期,负天范围设置,以及积极的一天范围的设置(这些,或者两者,可以为0):今天

DECLARE 
    @GET_DATE DATETIME 
    ,@DAY_RANGE_LOW SMALLINT 
    ,@DAY_RANGE_HIGH SMALLINT 
; 
SELECT 
    @GET_DATE = '02/23/2017' -- Thursday, Feb 23, 2017 
    ,@DAY_RANGE_LOW = -1  -- Allow me to see Wednesday, Feb 22, 2017, and today, Thursday, Feb 23, 2017 
    ,@DAY_RANGE_HIGH = 1  -- Allow me to see through Friday and Saturday into Sunday, Feb 26, 2017 
           -- Total days to view = 5 (Wed, Thurs, Fri, Sat, Sun) 
; 

告诉我,从陷入一系列@DAY_RANGE_LOW@DAY_RANGE_HIGH日期,排除间歇周五和周六从范围计算,但仍呈现要显示米为天:

SELECT 
    RowID 
    ,CONVERT(VARCHAR(10),Stamp,101) AS Stamp 
    ,CASE DATEPART(dw,Stamp) 
     WHEN 1 THEN 'Sunday' 
     WHEN 2 THEN 'Monday' 
     WHEN 3 THEN 'Tuesday' 
     WHEN 4 THEN 'Wednesday' 
     WHEN 5 THEN 'Thursday' 
     WHEN 6 THEN 'Friday' 
     WHEN 7 THEN 'Saturday' 
    END AS Weekday 
FROM @TABLE 
WHERE DATEDIFF(DAY,@GET_DATE, 
    DATEADD(DAY, 
    CASE 
     WHEN @DAY_RANGE_HIGH >= 1 
     AND DATEPART(dw,@GET_DATE) IN (5,6,7) 
     AND DATEPART(dw,Stamp) IN (6,7,1) 
     AND Stamp >= @GET_DATE 
     AND DATEDIFF(DAY,@GET_DATE,Stamp) BETWEEN -7 AND 7 
      THEN 
      CASE DATEPART(dw,Stamp) 
       WHEN 6 THEN -1 
       WHEN 7 THEN -2 
       WHEN 1 THEN -3 
      END 
     WHEN @DAY_RANGE_LOW <= -1 
     AND DATEPART(dw,@GET_DATE) = 1 
     AND DATEPART(dw,Stamp) IN (5,6,7) 
     AND Stamp <= @GET_DATE 
     AND DATEDIFF(DAY,@GET_DATE,Stamp) BETWEEN -7 AND 7 
      THEN 
      CASE DATEPART(dw,Stamp) 
       WHEN 5 THEN +3 -- Positive indicator added for clarity only 
       WHEN 6 THEN +2 
       WHEN 7 THEN +1 
      END 
     ELSE 0 
    END,Stamp)) BETWEEN @DAY_RANGE_LOW AND @DAY_RANGE_HIGH 
; 

该查询返回这个例子中,正确的结果,以及大多数其他例子到目前为止,我曾尝试:

RowID Stamp  Weekday  | [Logic] 
----------------------------------------------------- 
53  02/22/2017 Wednesday | [Today -1] 
54  02/23/2017 Thursday | [Today] 
55  02/24/2017 Friday  | [Intermittent] 
56  02/25/2017 Saturday | [Intermittent] 
57  02/26/2017 Sunday  | [Today +1] 

但它的笨拙和不雅,我不喜欢它。此外,如果客户选择使用最大设置,今天是星期六,我会看回最后一个星期六转发到下周日 - 但我不会看到,因为逻辑的局限性的最后一个星期日。不理想,但可生存。

这里提供的SQL只是一个很大的存储过程的小例子,它处理多个表之间的同步,但目前这是我们遇到问题的唯一部分。

无论我最终发现哪种解决方案都必须在SQL 2005中工作,最好也在SQL 2000中工作,因为我们的一些客户正在使用古老的服务器。

就如何更好地执行任何想法?

+0

我不会给这个作为一个答案,但因为你是时光倒流,你那么我只想说,日期时间内表示是浮动数字,每个数字是一天,因此你可以做一些有趣的技巧,比如像这样添加5天:“print cast((cast(getdate()as float)+ 5)as datetime)”。这不是任何人都会推荐的。 –

回答

1

该解决方案将要求您在表中添加一个额外的列,一个标记来表示日期是否是间歇性的。下面的代码应该得到你想要的。我在SQL Server 2016中进行了测试,但我认为我没有使用任何在2005年甚至2000年都无法使用的东西;它应该都是ANSI标准。此外,这是一个合适的SARG,所以如果你的索引建立在你的日期上,它应该利用这些索引来代替像当前版本那样进行全表扫描。

ALTER TABLE [Table] 
    ADD IsIntermittent BIT 
; 
GO 

UPDATE [Table] 
    SET IsIntermittent = CASE WHEN DATEPART(dw,Stamp) IN (5,6) THEN 0 ELSE 1 END 
; 

DECLARE @testdate DATETIME = '20160225' 
    ,@variation TINYINT = 2 
; 

SELECT * 
FROM [Table] 
WHERE Stamp BETWEEN 
(
    SELECT MIN(Stamp) 
    FROM 
    (
     SELECT 
      Stamp 
     FROM [Table] 
     WHERE Stamp < @testdate 
      AND IsIntermittent = 1 
     ORDER BY Stamp DESC 
     OFFSET 0 ROWS FETCH FIRST (@variation) ROWS ONLY 
    ) AS T 
) 
AND 
(
    SELECT MAX(Stamp) 
    FROM 
    (
     SELECT 
      Stamp 
     FROM [Table] 
     WHERE Stamp > @testdate 
      AND IsIntermittent = 1 
     ORDER BY Stamp 
     OFFSET 0 ROWS FETCH FIRST (@variation) ROWS ONLY 
    ) AS T 
) 
; 

此输出

RowID  Stamp     IsIntermittent 
----------- ----------------------- -------------- 
9550  2016-02-23 00:00:00.000 1 
9551  2016-02-24 00:00:00.000 1 
9552  2016-02-25 00:00:00.000 0 
9553  2016-02-26 00:00:00.000 0 
9554  2016-02-27 00:00:00.000 1 
9555  2016-02-28 00:00:00.000 1 
+0

大声笑我喜欢编辑。第一次你是对的......加一面旗子对我来说不会是个问题。 :-)稍后我会试一试,看看它是如何工作的,并回复你。非常感谢您付出的努力! – 3BK

相关问题