简体   繁体   English

MDX效率,来自同一层次结构的度量

[英]MDX Efficiency, measures from the same Hierarchy

I am fairly advanced at VBA / SQL . 我在VBA / SQL相当先进。

I am working on an extract from an SSAS cube in Excel to replace a pivot table. 我正在研究Excel中SSAS多维数据集的摘录以替换数据透视表。 I don't have access to the SQL server or SSMS . 我没有访问SQL serverSSMS权限。 For the first time I am extracting this information directly from the cube using MDX . 我是第一次使用MDX直接从多维数据集中提取此信息。

Much of the reason for this is to remove manual cube pivot table updates where issues have occurred with individuals overtyping the pivot table and / or not extending additional formulas down to match it. 这样做的大部分原因是要删除手动多维数据集枢轴表更新,在该更新中,由于个人过度设置了枢轴表和/或未向下扩展其他公式以使其匹配而出现问题。

I have produced a query which works for me, it is provided below (as loaded into the strMdx string in VBA ): 我产生了一个对我strMdx的查询,下面提供了该查询(在VBA加载到strMdx字符串中):

    strMDX = "WITH MEMBER [Measures].[Sector] as ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Sector]).NAME "
    strMDX = strMDX & "MEMBER [Measures].[Industry] as ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Industry]).NAME "
    strMDX = strMDX & "MEMBER [Measures].[Sub Industry] as ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Sub Industry]).NAME "
    strMDX = strMDX & "MEMBER [Measures].[Account] as ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Account]).NAME "
    strMDX = strMDX & "MEMBER [Measures].[Sub Account] as ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Sub Account]).NAME "
    strMDX = strMDX & "MEMBER [Measures].[Level] as ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Level]).NAME "
    strMDX = strMDX & "SELECT NON EMPTY ( {[Measures].[Sector], [Measures].[Industry], [Measures].[Sub Industry], [Measures].[Account], [Measures].[Sub Account], [Measures].[Level], "
    strMDX = strMDX & "[Measures].[iCounts] }) ON 0, "
    strMDX = strMDX & "NON EMPTY( [Date].[DayYear].[Year],[Date].[MonthYear].[MonthName]) ON 1, "
    strMDX = strMDX & "NON EMPTY( DESCENDANTS([Sector].[IndH],,LEAVES)) HAVING [Measures].[iCounts] >0 ON 2 FROM ( SELECT ( "
    strMDX = strMDX & "[Date].[MonthYear].[Date].&[" & Format(strStartDte, "yyyymmdd") & "]&[" & Format(strStartDte, "dd mmm yyyy") & "] : "
    strMDX = strMDX & "[Date].[MonthYear].[Date].&[" & Format(strEndDte, "yyyymmdd") & "]&[" & Format(strEndDte, "dd mmm yyyy") & "] ) "
    strMDX = strMDX & "ON 0 FROM [IndustryCube])"

This is the MDX : 这是MDX

WITH 
MEMBER [MeASures].[Sector] AS 
    ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Sector]).NAME 
MEMBER [MeASures].[Industry] AS 
    ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Industry]).NAME 
MEMBER [MeASures].[Sub Industry] AS 
    ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Sub Industry]).NAME 
MEMBER [MeASures].[Account] AS 
    ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Account]).NAME 
MEMBER [MeASures].[Sub Account] AS 
    ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Sub Account]).NAME 
MEMBER [MeASures].[Level] AS 
    ANCESTOR([Sector].[IndH].CURRENTMEMBER,[Sector].[IndH].[Level]).NAME 
SELECT 
NON EMPTY 
( 
    { [MeASures].[Sector]
    , [MeASures].[Industry]
    , [MeASures].[Sub Industry]
    , [MeASures].[Account]
    , [MeASures].[Sub Account]
    , [MeASures].[Level], 
      [MeASures].[iCounts] }
) ON 0, 
NON EMPTY 
    (
     [Date].[DayYear].[Year]
    ,[Date].[MonthYear].[MonthName]) ON 1, 
NON EMPTY
    (DESCENDANTS([Sector].[IndH],,LEAVES)) 
HAVING [MeASures].[iCounts] > 0 ON 2 
FROM ( 
    SELECT ( 
        [Date].[MonthYear].[Date].&[ & Format(strStartDte, yyyymmdd) ]&[ & Format(strStartDte, dd mmm yyyy) ] : 
        [Date].[MonthYear].[Date].&[ & Format(strEndDte, yyyymmdd) ]&[ & Format(strEndDte, dd mmm yyyy) ] ) 
        ON 0 
    FROM [IndustryCube]
)

There are two key aspects of this query to note: 此查询需要注意两个关键方面:

  1. It is a 3 axis query - which works perfectly for me in writing it using loops in VBA after. 这是一个3轴查询-在之后使用VBA中的循环编写它对我来说非常适合。
  2. I need to split out and use multiple levels from the same Hierarchy ( [Sector].[IndH] ), therefore I need to flatten the hierarchy. 我需要从同一层次结构( [Sector].[IndH] )中拆分并使用多个级别,因此我需要展平层次结构。 I have done this using Descendants then by defining each level as it's own measure. 我通过使用后代来完成此任务,然后将每个级别定义为自己的度量。 This does work to flatten out the hierarchy but I believe is a bit of a workaround. 这确实可以拉平层次结构,但我认为这是一种解决方法。

Other than the two points above I think it's a pretty standard MDX statement. 除了以上两点,我认为这是一个非常标准的MDX语句。

The key issue I have is that if I run this for say, a month or two, the query runs perfectly well, although it takes just over a minute. 我遇到的关键问题是,如果我说运行一两个月,则查询运行得很好,尽管只需要一分钟多的时间。 If I run it for over 5 years (which I need to) then it takes a significant amount of time and I have never got it to run successfully. 如果我运行了5年以上(我需要这样做),那么它将花费大量时间,而我从来没有使它成功运行。

Is there anything I can do to this query to improve it from a performance perspective? 从性能的角度来看,我可以对此查询做些什么来改善它?

I have a suspicion the issue is to do with flattening the hierarchy. 我怀疑问题与扁平化层次有关。 Unfortunately there is no way around this as the cube has not been set up with separate dimensions outside the hierarchy, or another hierarchy that contains the fields I need that I can pull from. 不幸的是,无法解决此问题,因为多维数据集尚未在层次结构或包含我可以从中提取的字段的另一个层次结构中设置单独的维度。

I'd be tempted to move it into a couple of mdx scripts within your vba , to try to make things a little more readable more than anything else. 我很想将它移到您的vba内的几个mdx脚本中,以尝试使事情更具可读性。

I'm guessing that in vba you're looping through the members that are in the third axis. 我猜想在vba您正在遍历第三轴中的成员。 If so take that out of your big script and create a small mdx script that returns these members. 如果是这样,请从大脚本中删除该脚本,并创建一个返回这些成员的小mdx脚本。 Maybe like: 可能像:

SELECT 
NON EMPTY 
    [MeASures].[iCounts] ON 0,  
NON EMPTY
    DESCENDANTS([Sector].[IndH],,LEAVES)  ON 1 
FROM ( 
    SELECT ( 
        [Date].[MonthYear].[Date].&[ & Format(strStartDte, yyyymmdd) ]&[ & Format(strStartDte, dd mmm yyyy) ] : 
        [Date].[MonthYear].[Date].&[ & Format(strEndDte, yyyymmdd) ]&[ & Format(strEndDte, dd mmm yyyy) ] ) 
        ON 0 
    FROM [IndustryCube]
)

The outer loop could iterate over the members returned from the above and feeds each into the following: 外循环可以遍历从上面返回的成员,并将每个成员馈入以下内容:

SELECT 
NON EMPTY 
    [MeASures].[iCounts]  ON 0, 
NON EMPTY 
    [Date].[DayYear].[Year]
    *[Date].[MonthYear].[MonthName]
    *[Sector].[IndH].[Sector]
    *[Sector].[IndH].[Industry]
    *[Sector].[IndH].[Sub Industry]
    *[Sector].[IndH].[Account]
    *[Sector].[IndH].[Sub Account]
    *[Sector].[IndH].[Level] ON 1 
FROM 
( 
    SELECT  
        [Date].[MonthYear].[Date].&[ & Format(strStartDte, yyyymmdd) ]&[ & Format(strStartDte, dd mmm yyyy) ] : 
        [Date].[MonthYear].[Date].&[ & Format(strEndDte, yyyymmdd) ]&[ & Format(strEndDte, dd mmm yyyy) ]  
        ON 0, 
        [Sector].[IndH].&[ ....strFromOuterLoopHere...  ON 1
    FROM [IndustryCube]
);

One thing to be wary about when using mdx are braces (..) - this indicates to the processor that you want to create a tuple; 大括号(..)是在使用mdx时要警惕的一件事-这表明处理器要创建一个元组。 the script in your question has quite a few extra braces. 您问题中的脚本有很多额外的花括号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM