【问题标题】:MDX - Top N, Order by Dimension and MeasureMDX - 前 N 个,按维度和度量排序
【发布时间】:2017-02-27 14:42:18
【问题描述】:

我正在尝试编写一个相当简单(至少在 SQL 中)的 MDX 查询,但没有成功。

一些数据洞察:

  • 我正在制作一份 TOP 10 国家/地区报告
  • 前 10 个国家/地区绑定在最近选择的年份(在本例中为 2016 年)
  • 如果2016年没有国家,我必须从2015年(仅过去一年)进入前10名
  • 如果 2016 年只有 3 个国家/地区,我必须从 2015 年开始选择 7 个

该报告在 SQL 中运行良好,但我似乎无法在 MDX 中进行相同的操作。

我能做什么(但不确定这是正确的方法):

  • 我每年使用 generate 语句获取前 10 个国家/地区(一项衡量标准中排名前 10)
  • 我按年份维度排序(我每年有 10 个国家,按年份 DESC 排序)

当前脚本

 SELECT 
    NON EMPTY
    { 
        [Measures].[MeasureX]
    } ON COLUMNS, 

    NON EMPTY
    {
        Generate
        (
            ORDER
            (
                [Date].[Year].[Year].ALLMEMBERS,
                [Date].[Year].CurrentMember.Properties("Member_Value"), 
                DESC
            ),
            { [Date].[Year].CurrentMember } *
            TOPCOUNT
                (
                    [Person].[Country].[Country].MEMBERS, 
                    10, 
                    [Measures].[MeasureX]
                )
        )
    } ON ROWS 
 FROM 
    [Cube]

这几乎是我需要的(但同样 - 可能不是最好的方法)。我现在得到 N 行数据,就像这样(为了论证,我写的就像我想将它限制为 5 行一样):

Argentina 1000 2016
Bulgaria 500 2016
USA 444 2016
Germany 8000 2015
Canada 4000 2015
Netherlands 2000 2015

当我在我的 mdx 上放置一个 HEAD(限制为 5 个)时,我得到了一个时髦的结果:

Argentina 1000 2016
Bulgaria 500 2016
USA 444 2016
Germany null 2016
Canada null 2016

我错过了什么。正确的方法是什么?

编辑 2017-02-28:

我正在尝试在 OLAP 中实现这一点:

;WITH CTE_Subset AS
(
SELECT TOP 50
    YEAR(fis.OrderDate) AS Year,
    SUM(fis.SalesAmount) AS SalesAmount,
    dg.CountryRegionCode
FROM
    dbo.FactInternetSales fis
INNER JOIN
    dbo.DimCustomer dc ON dc.CustomerKey = fis.CustomerKey
INNER JOIN
    dbo.DimGeography dg ON dg.GeographyKey = dc.GeographyKey
GROUP BY
    YEAR(fis.OrderDate),
    dg.CountryRegionCode
ORDER BY
    YEAR(fis.OrderDate) DESC, 
    SUM(fis.SalesAmount) DESC
)
SELECT DISTINCT TOP 10
    CountryRegionCode 
FROM 
    CTE_SubSet 

【问题讨论】:

  • 您只是想知道如何使用 HEAD 来限制您编写的脚本的结果?或者您希望脚本执行更多操作?

标签: reporting-services ssas mdx


【解决方案1】:

使用 AdvWrks 而不使用 GENERATE 我们可以执行以下操作:

WITH 
  SET [countryYear] AS 
    Order
    (
      NonEmpty
      (
          [Customer].[Customer Geography].[Country]
        * 
          [Date].[Calendar].[Calendar Year]
       ,[Measures].[Internet Sales Amount]
      )
     ,[Measures].[Internet Sales Amount]
     ,bdesc
    ) 
SELECT 
  [Measures].[Internet Sales Amount] ON 0
 ,Head
  (
    [countryYear]
   ,10
  ) ON 1
FROM [Adventure Works];

结果如下,这与您的要求相似吗?

我们可以使用子选择来获得 50 个 - 在 AdvWrks 中,50 个国家中只有 4 个不同的国家:

SELECT 
  {} ON 0
 ,[Customer].[Customer Geography].[Country] ON 1
FROM 
(
  SELECT 
    Head
    (
      Order
      (
        NonEmpty
        (
            [Customer].[Customer Geography].[Country]
          * 
            [Date].[Calendar].[Calendar Year]
         ,[Measures].[Internet Sales Amount]
        )
       ,[Measures].[Internet Sales Amount]
       ,bdesc
      )
     ,50
    ) ON 0
  FROM [Adventure Works]
);

结果:

【讨论】:

  • 很抱歉,但这不是我想要实现的目标。你能看看我的问题的编辑部分吗?
  • @user3652540 在 sql 中是否首先应用 DISTINCT 或 TOP 在这句话SELECT DISTINCT TOP 10 ...
  • 首先是不同的(所以你得到所有不同的国家,按子集排序 - 按年份和度量),然后从这个不同的值中,你得到前 10 个
【解决方案2】:

我没有尝试过下面的代码,但您可以重用这个想法:使用特殊度量生成每个国家/地区,开头为年份值,结尾为 MeasureX(即:201600001000)。但是,如果您有巨大的 MeasureX 值,100000000000 可能还不够。

With
Member [Measures].[MeasureY] as
IIF(
    IsEmpty([Measures].[MeasureX]),
    Null,
    [Date].[Year].CurrentMember.Properties("Member_Value") * 100000000000 + [Measures].[MeasureX]
)

SELECT 
    NON EMPTY
    { 
        [Measures].[MeasureX]
    } ON COLUMNS, 

    NON EMPTY
    {
    TopCount(
        Generate(
            [Person].[Country].[Country].Members,
            TopCount(
                [Date].[Year].[Year].Members, 
                1, 
                [Measures].[MeasureY]
            )
        ),
        10,
        [Measures].[MeasureY]       
    )
    } ON ROWS 
 FROM 
    [Cube]

【讨论】:

    猜你喜欢
    • 2016-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多