将 "YYYYWW" 转换为月 (SSRS)

Convert "YYYYWW" into month (SSRS)

我正在创建一个报告,并希望根据 YYYYWW 格式的日期字段(字符串)检索数据。我想过滤数据,以便检索当前月份、上个月、前一个月和更旧的值 - 使用 4 个不同的数据集。

例如: 201547 = November 2015

如何创建将字符串转换为月份名称和年份的计算成员?我想使用这个值从多维数据集中过滤掉数据。还有其他方法吗?

:]1

第 1 部分:确定哪一天属于哪一周
ISO-8601 声明了将日期转换为周数的国际标准,反之亦然。

ISO 标准周从星期一开始。一年可以有 52 周或 53 周。

有 4 种方法可以确定第 1 周的开始时间:
- 这是第一周,大部分时间(4 天或更多)在 1 月。
- 它的第一天是离 1 月 1 日最近的星期一。
- 它有 1 月 4 日。因此,最早的日期是 12 月 29 日至 1 月 4 日,最晚的日期是 1 月 4 日至 10 日。
- 它包含一年中的第一个工作日 - 即不包括周六、周日和 1 月 1 日。

第 2 部分:Excel 计算

此答案假定日期存储为 6 个字符的字符串。

首先确定年份和星期几。

1) Strip the first four characters from the string.`  
    =left(<cell containing the year+week string>, 4)
2) Prepend "1/1/" to it.
    ="1/1/"&left(<cell containing the year+week string>, 4)
3) Convert this string to an Excel date    
    =datevalue(<the last result>)
4) Determine the Weekday of the 1st day of that year.  
    =weekday(<the last result>)
5) Calculate the Excel date of the first Monday.
    =if((<the last result>-4)<0,<the result of step 3>+8-<the last result>, <the result of step 3>+1-<the last result>)
6) Work out how many weeks on from that we are:
    =right(<original 6 char year/week string>,2)
7) Convert 6) to a number
    =value(<last result>)
8) Add that to the Monday of Week 1   
    =<result of step 5>+<result of step 7>*7
9) Convert this to a month number
    =month(<last result>)
10) Convert this to a month name
    =choose(<last result>,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
11) Add the year back on
    =<lastresult>&" "&<result of 1>

这给出了包含当前编号周的星期一的月份编号。

如果单元格 A1 包含 '201547 那么单元格 B1 应该包含: =CHOOSE(MONTH(IF((WEEKDAY(DATEVALUE("1/1/"&LEFT(A1,4)))-4)<0,DATEVALUE("1/1/"&LEFT(A1,4))+1-WEEKDAY(DATEVALUE("1/1/"&LEFT(A1,4))),DATEVALUE("1/1/"&LEFT(A1,4))+8-WEEKDAY(DATEVALUE("1/1/"&LEFT(A1,4))))+7*(VALUE(RIGHT(A1,2)))),"January","February","March","April","May","June","July","August","September","October","November","December")&" "&LEFT(A1,4)

如果 A1 包含 201547 那么 B1 returns "November 2015".

进一步考虑: 您可能希望使其更复杂,以便以星期一结束的月份不会将以其最后一个星期一开始的那一周算作该月的一部分。更一般地说,当月有 3 天或更多天数时,该周仅算作一个月的一部分。或 3 个或更多的工作日是该月的一部分。

实际上,我将以计算出的月份和年份作为主键,以 YYYYMM 代码作为辅助键进行排序。

结合使用在 Internet 上找到的资源,您可以找到所需的信息。

首先你需要找到一年中第一周的第一天。这已经被 this answer 确定为

DateAdd("d", 
    (-1) * (CInt(New DateTime(Year(Now), 1, 1).DayOfWeek) + 
    IIf(CInt(New DateTime(Year(Now), 1, 1).DayOfWeek) < DayOfWeek.Monday, 
        7, 
        0)
    ) + 1, 
    New DateTime(Year(Now), 1, 1))

这需要针对任何年份进行调整 - 而不仅仅是当前年份,方法是从字符串中查找年份,如下所示

CInt(Left(Parameters!myDate.Value,4))

现在,如 this resource 中所述,您可以使用 DateAdd 将您输入的一年中的周数添加到一年中的第一个日期

=(DateAdd(DateInterval.WeekOfYear,
    CInt(Right(Parameters!myDate.Value,2))-1,
    <<FIRST_DAY_OF_YEAR>>)

然后您想要使用 MonthMonthName 获取该日期所在月份的月份名称。将它们全部粉碎会导致以下结果

=MonthName(Month(DateAdd(DateInterval.WeekOfYear,
    CInt(Right(Parameters!myDate.Value,2))-1,
    DateAdd("d", 
        (-1) * (CInt(New DateTime(CInt(Left(Parameters!myDate.Value,4)), 1, 1).DayOfWeek) + 
        IIf(CInt(New DateTime(CInt(Left(Parameters!myDate.Value,4)), 1, 1).DayOfWeek) < DayOfWeek.Monday, 
            7, 
            0)
        ) + 1, 
        New DateTime(CInt(Left(Parameters!myDate.Value,4)), 1, 1))      
    )))

这将获得间隔月份的文本值

在同一个文本框中创建一个新的占位符,然后重复上面的步骤来查找年份

=Year(DateAdd(DateInterval.WeekOfYear, ...

(记得去掉最后一个大括号,否则你会得到一个 End of Statement expected 错误。)

这应该能满足您的需求,所以

201501 = December 2014
201547 = November 2015
201553 = December 2015
201622 = May 2016

让我知道这是否有帮助,或者如果您还有其他问题

尝试添加计算字段并将其设置为此表达式:

=MonthName(Month(DateAdd("ww",CInt(MID("201547",5,LEN("201547")))
,DateSerial(CInt(LEFT("201547",4)),1,1)))) & " " & LEFT("201547",4)

然后使用该字段来过滤您的报告。

替换返回“201547”的字段的字符串

=MonthName(Month(DateAdd("ww",
CInt(MID(Fields!YearWeek.Value,5,LEN(Fields!YearWeek.Value)))
,DateSerial(CInt(LEFT(Fields!YearWeek.Value,4)),1,1))))
& " " & LEFT(Fields!YearWeek.Value,4)

更新: 用于查询具有所需格式的计算成员的 MDX 脚本:

我已经使用以下 MDX 进行了测试:

WITH MEMBER [Measures].[month&year] AS
  'FORMAT(DateAdd("ww",STRTOVALUE(MID("201547",5,LEN("201547"))) ,CDATE(DateSerial(LEFT("201547",4),1,1))),"MMMM") + " " + LEFT("201547",4)'
SELECT { [month&year] } ON COLUMNS
FROM [Your Cube]

要在您的查询中使用它,请将 "201547" 替换为对应于您的多维数据集结构的 [Dimension].[Attribute].MemberValue

WITH  MEMBER [Measures].[month&year] as 
'FORMAT(DateAdd("ww",STRTOVALUE(MID([Dimension].[Attribute].MemberValue,5,LEN([Dimension].[Attribute].MemberValue)))
,CDATE(DateSerial(LEFT([Dimension].[Attribute].MemberValue,4),1,1))),"MMMM") + " " + LEFT([Dimension].[Attribute].MemberValue,4)'
SELECT
   { [Dimension].[Attribute].[Attribute] }
   {[month&year]} ON COLUMNS
FROM [Your Cube]

在数据集中拥有此字段后,您可以使用参数轻松过滤值。

如果这对您有帮助,请告诉我。