【问题标题】:SSRS - Month not starting on correct daySSRS - 月份不是从正确的日期开始
【发布时间】:2016-12-13 18:08:33
【问题描述】:

我正在尝试制作一份报告,为每个月生成一个日历,用户可以在其中指定月份和年份的范围。我的矩阵在Weekday 上有一个列分组,而行分组在WeekNumber 上(请参阅下面的查询结果)。

我遇到的问题是这一天开始的地方不对如下所示:

这是因为我的查询只包含该特定月份的天数,而不是之前和之后月份的几天,通常会在日历上显示为灰色:

虽然我怀疑这个问题也可以在矩阵本身中解决,但我不确定在查询中解决它还是在矩阵中解决它会比另一个更好。

我当前的查询:

SELECT  t1.[TimeSheetLineID] ,
        t1.[TimeSheetID] ,
        t1.[JobID] ,
        t1.[TimeSheetDate] ,
        t1.[TimeSheetCreatedOn] ,
        t1.[TimeSheetLastModifiedOn] ,
        t1.[StartTime] ,
        t1.[EndTime] ,
        t1.[TotalTime] ,
        t1.[EmployeeName] ,
        t2.DateFull ,
        t2.[FullYear] ,
        t2.[WeekNumber] ,
        t2.[WeekDay] ,
        t2.[WeekDayName] ,
        t2.[MonthDay] ,
        t2.[MonthName] ,
        t2.[MonthNumber]
FROM    dbo.DateLookup t2
LEFT JOIN [dbo].[FactTimeSheets] t1 
  ON t1.TimeSheetDate = t2.DateFull
  AND (t1.JobID = @jobNumber) 
WHERE (t2.FullYear = @year) 
  AND (t2.MonthNumber BETWEEN @startMonth AND @endMonth)
ORDER BY FullYear, MonthNumber, MonthDay, WeekDay

当前查询结果(通知WeekDay 8 月份以 2 开头):

基于this article

--更新--

我在下面的查询中使用 CTE 来获取填写此日历所需的额外日期。我在 Date 表上对其进行了测试,明天将使用最终查询更新我的答案:

DECLARE @year INT ,
    @startMonth DATE ,
    @endMonth DATE;
SET @year = '2016';
SET @startMonth = '2016-08-01';
SET @endMonth = '2016-08-31';

DECLARE @StartDate DATE ,
    @EndDate DATE;
SET @StartDate = DATEADD(s, 0, DATEADD(mm, DATEDIFF(m, 0, @startMonth), 0));
SET @StartDate = DATEADD(DAY, -DATEPART(WEEKDAY, @StartDate) + 1, @StartDate);
--SELECT @StartDate

SET @EndDate = DATEADD(s, -1, DATEADD(mm, DATEDIFF(m, 0, @startMonth) + 1, 0));
SET @EndDate = DATEADD(DAY, 7 - DATEPART(WEEKDAY, @EndDate), @EndDate)
--SELECT @EndDate;
;

WITH    Dates ( [Date] )
          AS (
   --Select First day in range
               SELECT   CONVERT(DATETIME, @StartDate) AS [Date]
               UNION ALL
   --Add a record for every day in the range
               SELECT   DATEADD(DAY, 1, [Date])
               FROM     Dates
               WHERE    Date < CONVERT(DATETIME, @EndDate)
             ),
        Events
          AS ( SELECT   [FullYear] ,
                        [DateFull] ,
                        [WeekNumber] ,
                        [WeekDay] ,
                        [WeekDayName] ,
                        [MonthDay] ,
                        [MonthName] ,
                        [MonthNumber]
               FROM     [dbo].[DateLookup]
             )
    SELECT  e.[FullYear] ,
            e.[DateFull] ,
            d.[Date] ,
            e.[WeekNumber] ,
            e.[WeekDay] ,
            e.[WeekDayName] ,
            e.[MonthDay] ,
            e.[MonthName] ,
            e.[MonthNumber]
    FROM    Dates d
            LEFT JOIN Events e ON d.[Date] = CAST(e.DateFull AS DATE)
    GROUP BY FullYear ,
            MonthNumber ,
            DateFull ,
            d.[Date] ,
            WeekNumber ,
            MonthName ,
            WeekDayName ,
            MonthDay ,
            WeekDay
    ORDER BY Date;

--最终更新的查询--

我希望这对将来的人有所帮助。

SET @startDate = DATEADD(mm, DATEDIFF(m, 0, CAST(CAST(@year AS varchar) + '-' + CAST(@startMonth AS varchar) + '-01' AS DATETIME)), 0);
SET @startDate = DATEADD(DAY, -DATEPART(WEEKDAY, @startDate) + 1, @startDate);

SET @endDate = DATEADD(mm, DATEDIFF(m, 0, CAST(CAST(@year AS varchar) + '-' + CAST(@endMonth AS varchar) + '-01' AS DATETIME)) + 1, 0);
SET @endDate = DATEADD(DAY, 7 - DATEPART(WEEKDAY, @endDate), @endDate);

WITH    Dates ( [Date] )
          AS ( SELECT   CONVERT(DATETIME, @startDate) AS [Date]
               UNION ALL
               SELECT   DATEADD(DAY, 1, [Date])
               FROM     Dates
               WHERE    Date < CONVERT(DATETIME, @endDate)
             ),
        Events
          AS ( SELECT   t1.[TimeSheetLineID] ,
                        t1.[TimeSheetID] ,
                        t1.[JobID] ,
                        t1.[TimeSheetDate] ,
                        t1.[TimeSheetCreatedOn] ,
                        t1.[TimeSheetLastModifiedOn] ,
                        t1.[StartTime] ,
                        t1.[EndTime] ,
                        t1.[TotalTime] ,
                        t1.[EmployeeName] ,
                        t1.[CostCategory] ,
                        t2.[DateFull] ,
                        t2.[FullYear] ,
                        t2.[WeekNumber] ,
                        t2.[WeekDay] ,
                        t2.[WeekDayName] ,
                        t2.[MonthDay] ,
                        t2.[MonthName] ,
                        t2.[MonthNumber]
               FROM     dbo.DateLookup t2
                        LEFT JOIN [dbo].[FactTimeSheets] t1 ON t1.TimeSheetDate = t2.DateFull
                                                              AND ( t1.JobID = @jobNumber )
               WHERE    ( t2.FullYear = @year )
             )
    SELECT  e.[TimeSheetLineID] ,
            e.[TimeSheetID] ,
            e.[JobID] ,
            e.[TimeSheetDate] ,
            e.[TimeSheetCreatedOn] ,
            e.[TimeSheetLastModifiedOn] ,
            e.[StartTime] ,
            e.[EndTime] ,
            e.[TotalTime] ,
            e.[EmployeeName] ,
            e.[CostCategory] ,
            e.[DateFull] ,
            d.[Date] ,
            e.[FullYear] ,
            e.[WeekNumber] ,
            e.[WeekDay] ,
            e.[WeekDayName] ,
            e.[MonthDay] ,
            e.[MonthName] ,
            e.[MonthNumber]
    FROM    Dates d
            LEFT JOIN Events e ON d.[Date] = CAST(e.DateFull AS DATE)
    ORDER BY Date;

【问题讨论】:

  • 您可以在每天返回一个标志,指示它是否应该变灰。我也有这个问题。您可能需要在上个月和下个月中加入几天来平衡您的日历。
  • 嗨@RossBush,您是在查询中解决了这个问题,还是在矩阵中以某种方式解决了这个问题?感谢您的评论!
  • 我返回了星期一或星期日,但是您将一周的第一天配置为范围的第一天,然后计算该月的最后一天并添加最后一天的任何溢出天数星期。因此,如果最后一天是星期二,那么我返回该周的星期日作为范围的最后一天,这样我就可以添加溢出灰色效果。但是,您需要在查询中标记溢出天数,以便在矩阵中将它们涂成灰色。
  • 在查询中,CalendarBlockNumber 不一定是 DayNumberInMonth。
  • 您能否使用 CTE 与您的月份联合,以便用前一天的最后几天和下个月的第一天填充它?

标签: sql reporting-services ssrs-2008-r2 ssrs-tablix


【解决方案1】:

您可以将日期分组到一个矩阵中以获得正确的布局。

插入一个矩阵。按工作日(数字)对列进行分组和排序。按周数对行进行分组和排序。它应该是这样的:

现在当你运行它时,它会变成这样:

【讨论】:

  • 嗨@StevenWhite,感谢您的回答,我更新了我的问题以表明这就是我所拥有的,但我的矩阵出现了不同的结果。您能否更新您的答案以显示您用于此结果的查询?
  • 您是如何将这些值转移过来的?您是否使用了任何组表达式或其他任何东西?
  • @JonathanPorter 查询没有什么特别之处。只要您对周数和天数进行分组和排序,它就应该是正确的。如果您真的在工作日分组,则 1 不能在星期一列中。您的原始查询结果看起来正确。
  • 我的分组中缺少排序。谢谢!
【解决方案2】:

最终答案:

SET @startDate = DATEADD(mm, DATEDIFF(m, 0, CAST(CAST(@year AS varchar) + '-' + CAST(@startMonth AS varchar) + '-01' AS DATETIME)), 0);
SET @startDate = DATEADD(DAY, -DATEPART(WEEKDAY, @startDate) + 1, @startDate);

SET @endDate = DATEADD(mm, DATEDIFF(m, 0, CAST(CAST(@year AS varchar) + '-' + CAST(@endMonth AS varchar) + '-01' AS DATETIME)) + 1, 0);
SET @endDate = DATEADD(DAY, 7 - DATEPART(WEEKDAY, @endDate), @endDate);

WITH    Dates ( [Date] )
          AS ( SELECT   CONVERT(DATETIME, @startDate) AS [Date]
               UNION ALL
               SELECT   DATEADD(DAY, 1, [Date])
               FROM     Dates
               WHERE    Date < CONVERT(DATETIME, @endDate)
             ),
        Events
          AS ( SELECT   t1.[TimeSheetLineID] ,
                        t1.[TimeSheetID] ,
                        t1.[JobID] ,
                        t1.[TimeSheetDate] ,
                        t1.[TimeSheetCreatedOn] ,
                        t1.[TimeSheetLastModifiedOn] ,
                        t1.[StartTime] ,
                        t1.[EndTime] ,
                        t1.[TotalTime] ,
                        t1.[EmployeeName] ,
                        t1.[CostCategory] ,
                        t2.[DateFull] ,
                        t2.[FullYear] ,
                        t2.[WeekNumber] ,
                        t2.[WeekDay] ,
                        t2.[WeekDayName] ,
                        t2.[MonthDay] ,
                        t2.[MonthName] ,
                        t2.[MonthNumber]
               FROM     dbo.DateLookup t2
                        LEFT JOIN [dbo].[FactTimeSheets] t1 ON t1.TimeSheetDate = t2.DateFull
                                                              AND ( t1.JobID = @jobNumber )
               WHERE    ( t2.FullYear = @year )
             )
    SELECT  e.[TimeSheetLineID] ,
            e.[TimeSheetID] ,
            e.[JobID] ,
            e.[TimeSheetDate] ,
            e.[TimeSheetCreatedOn] ,
            e.[TimeSheetLastModifiedOn] ,
            e.[StartTime] ,
            e.[EndTime] ,
            e.[TotalTime] ,
            e.[EmployeeName] ,
            e.[CostCategory] ,
            e.[DateFull] ,
            d.[Date] ,
            e.[FullYear] ,
            e.[WeekNumber] ,
            e.[WeekDay] ,
            e.[WeekDayName] ,
            e.[MonthDay] ,
            e.[MonthName] ,
            e.[MonthNumber]
    FROM    Dates d
            LEFT JOIN Events e ON d.[Date] = CAST(e.DateFull AS DATE)
    ORDER BY Date;

【讨论】:

    【解决方案3】:

    8 月 1 日是星期一,所以工作日应该是 1。但在你的桌子上是 2

    【讨论】:

    • 嗨 Sepehr,您查看的是 WeekDay 而不是 MonthDay。星期日被认为是一周的开始 (1),这就是为什么星期一 = 2。但 MonthDay 显示它是该特定月份的开始日期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 2019-01-24
    相关资源
    最近更新 更多