计算日期范围内的星期六数-SQL

时间:2019-08-20 08:07:48

标签: sql-server datetime casting count

我有一个报告,该报告在给定日期范围内寻找订单...它从报告中返回DateName以给我星期一,然后从报告中给我时间,例如给08:59给我859 ..然后我在此报告上使用一个案例来执行以下操作...

WHEN (DATENAME(DW,T1.DocDate)) = 'Monday' AND T1.DocTime >= '700' AND T1.DocTime <= '859' THEN '1 Monday 07:00-08:59'

我想要实现的是,如果有2个星期一,则将“ 1 Monday 07:00-08:59”的计数除以2,如果有3个星期一,则除以3,依此类推...例如,我必须能够将其除以3个星期一,但是如果日期是星期二,则可以除以2个星期三...

该报告当前给出了一个日期时间内所有订单的总计,这些订单被分组在一起,但是没有除以每天的平均值。

SELECT (DATENAME(DW, T1.DocDate)) AS Weekday,
       T1.DocTime AS Time,
       SUM(T1.DocTotal) AS Value,
       CASE
            WHEN (DATENAME(DW, T1.DocDate)) = 'Monday'
             AND T1.DocTime >= '700'
             AND T1.DocTime <= '859' THEN '1 Monday 07:00-08:59'
FROM ORDR T1
     INNER JOIN OCRD T0 ON T0.CardCode = T1.CardCode
WHERE (T1.DocDate >= @Start
   AND T1.DocDate <= @End)
  AND T0.QryGroup20 = 'Y'
  AND T1.Canceled = 'N'
GROUP BY T1.DocTime,
         T1.DocDate;

我希望报告会计算@START和@END之间的星期一/星期二等,以便为我提供每天和时间的平均销售额。然后可以在某种情况下除以定义的天数声明。 (我希望可以在Crystal Reports中做这部分),但是如果我可以得到第一部分,那么我将在下半部分工作。

2 个答案:

答案 0 :(得分:0)

您可以使用以下逻辑-

对于MSSQL

DECLARE @DT1 DATE = '20190802'
DECLARE @DT2 DATE = '20190820'

DECLARE @SatCount INT = 0

WHILE @DT1<= @DT2
BEGIN

    SET @SatCount = @SatCount + CASE WHEN DATEPART(WeekDay,@DT1) = 7 THEN 1 ELSE 0 END

    SET @DT1 = DATEADD(DD,1,@DT1)
END


SELECT @SatCount

只需一个选项-

DECLARE @DT1 DATE = '20190802',
        @DT2 DATE = '20190920';


SELECT SUM(CASE WHEN DATEPART(WeekDay,Date) = 7 THEN 1 ELSE 0 END) 
FROM
(
    SELECT  TOP (DATEDIFF(DAY, @DT1, @DT2) + 1)
            Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @DT1)
    FROM    sys.all_objects a 
    -- A System table just used for creating multiple rows. 
    CROSS JOIN sys.all_objects b
    -- CROSS JOIN will create number of row = original number of row X original number of row. 
)A

答案 1 :(得分:0)

只需交叉联接DW_Count子查询,该查询就会返回您订单范围内每个工作日的计数。然后,您可以计算每个工作日的平均值

SELECT (DATENAME(DW, T1.DocDate)) AS Weekday,
   T1.DocTime AS Time,
   SUM(T1.DocTotal) AS Value,
   SUM(T1.DocTotal)/(CASE WHEN DATENAME(DW, T1.DocDate) = 'Monday' then DW_Count.MonCount
                            WHEN DATENAME(DW, T1.DocDate) = 'Tuesday' then DW_Count.TueCount
                            WHEN DATENAME(DW, T1.DocDate) = 'Wednesday' then DW_Count.WedCount
                            WHEN DATENAME(DW, T1.DocDate) = 'Thursday' then DW_Count.ThuCount
                            WHEN DATENAME(DW, T1.DocDate) = 'Friday' then DW_Count.FriCount
                            WHEN DATENAME(DW, T1.DocDate) = 'Saturday' then DW_Count.SatCount
                            WHEN DATENAME(DW, T1.DocDate) = 'Sunday' then DW_Count.SunCount) AS AvgValue
   CASE
        WHEN (DATENAME(DW, T1.DocDate)) = 'Monday'
         AND T1.DocTime >= '700'
         AND T1.DocTime <= '859' THEN '1 Monday 07:00-08:59'    
FROM ORDR T1
 INNER JOIN OCRD T0 ON T0.CardCode = T1.CardCode
 CROSS JOIN (select sum(case when DATENAME(DW, DW_Count.DateValue) = 'Monday' then 1 else 0 end) as MonCount,
    sum(case when DATENAME(DW, DW_Count.DateValue) = 'Tuesday' then 1 else 0 end) as TueCount,
    sum(case when DATENAME(DW, DW_Count.DateValue) = 'Wednesday' then 1 else 0 end) as WedCount,
    sum(case when DATENAME(DW, DW_Count.DateValue) = 'Thursday' then 1 else 0 end) as ThuCount,
    sum(case when DATENAME(DW, DW_Count.DateValue) = 'Friday' then 1 else 0 end) as FriCount,
    sum(case when DATENAME(DW, DW_Count.DateValue) = 'Saturday' then 1 else 0 end) as SatCount,
    sum(case when DATENAME(DW, DW_Count.DateValue) = 'Sunday' then 1 else 0 end) as SunCount
        from (select distinct DocDate from ORDR where (T1.DocDate >= @Start AND T1.DocDate <= @End))) AS DW_Count
WHERE (T1.DocDate >= @Start
   AND T1.DocDate <= @End)
  AND T0.QryGroup20 = 'Y'
  AND T1.Canceled = 'N'
GROUP BY T1.DocTime,
         T1.DocDate;