SSAS多维模型按维度分组排序时重复报错问题解决方案问询
问题描述
我使用版本13的SQL Server Analysis Services(多维模式),需要在Excel数据透视表中展示分析结果,需求如下:
- 计划通过
ClientSelect表将客户划分到不同组别,采用Platform / Type的层级结构,每个Type下取Top 20客户,层级示例如下:Platform / Type All Games YTD Top Winner YTD Most Played YTD Most Liked Chess YTD Top Winner YTD Most Played YTD Most Liked - 由于同一个客户可能出现在多个名单中,我用多对多事实表
ClientSelectMap关联客户表和ClientSelect表。
目前基础功能已经可以正常运行:我可以展示All Games分类下YTD Top Winner的前20名,也可以查看对应昨日数据。但我希望YTD Top Winner的20名客户能够按照YTD获胜次数、对局数或点赞数排序,我在DimClientSelect表中添加了OrderBy属性,但是每次尝试将该属性与Type属性关联,以便在OrderByAttribute字段中使用它为Type排序时,都会触发重复报错。
请问这种场景下我该如何对返回的客户进行排序?是否需要将排序字段放在关联表中?
提前致谢
Hamish
(原问题附结构示意图)
解决方案
你遇到的重复报错核心原因是:DimClientSelect是存储分组规则的维度表,同一个Type(比如YTD Top Winner)对应多个客户的排序值,直接把OrderBy属性和Type属性绑定会出现重复键,不符合SSAS多维维度属性的键唯一要求。针对你的场景有两种成熟的实现方案:
方案1:用度量值实现动态排序(最灵活,适配Excel用户自定义排序需求)
不需要修改现有维度结构,直接通过度量值实现排序,同时支持用户切换排序规则:
- 先在事实度量值组中创建三个基础度量:
YTD获胜次数、YTD对局数、YTD点赞数,按业务需求设置聚合规则即可。 - (可选)新建独立的「排序规则」维度,成员为三个排序规则选项,不需要关联任何事实表。
- 创建动态排序度量值,MDX示例如下:
CREATE MEMBER CurrentCube.[Measures].[动态排序值] AS CASE [排序规则维度].[排序规则].CurrentMember WHEN [排序规则维度].[排序规则].&[按YTD获胜次数] THEN [Measures].[YTD获胜次数] WHEN [排序规则维度].[排序规则].&[按YTD对局数] THEN [Measures].[YTD对局数] WHEN [排序规则维度].[排序规则].&[按YTD点赞数] THEN [Measures].[YTD点赞数] ELSE [Measures].[YTD获胜次数] END
- Excel用户在透视表中直接右键客户列,选择「排序」→「按度量值排序」,选中对应排序度量即可完成排序,不需要额外配置SSAS属性。
方案2:固定Type对应排序规则(适合每个分组排序逻辑固定的场景)
如果要求YTD Top Winner固定按获胜次数排序、YTD Most Played固定按对局数排序,可以把排序值存在多对多映射表中:
- 在
ClientSelectMap表新增两个字段:SortOrder(存储当前客户在对应ClientSelect分组中的排序序号,1~20唯一)、SortMetricValue(存储对应排序指标的具体数值)。 - 处理SSAS维度时,将
SortOrder作为DimClientSelect维度Type属性的关联属性,设置Type属性的KeyColumns为复合键:PlatformID + TypeID + SortOrder,即可解决重复键报错问题。 - 把Type属性的
OrderByAttribute设置为SortOrder,处理部署后即可实现固定排序。
额外优化建议
如果需要强制每个Type下只返回Top20客户,避免Excel展示冗余数据,可以在SSAS的MDX脚本中添加作用域限制:
SCOPE([DimClientSelect].[Type].[Type].Members, [DimClient].[ClientID].Members); THIS = IIF(RANK([DimClient].[ClientID].CurrentMember, NONEMPTY([DimClient].[ClientID].[ClientID].Members, [Measures].[动态排序值]), [Measures].[动态排序值]) <=20, [Measures].CurrentMember, NULL); NON_EMPTY_BEHAVIOR(THIS) = [Measures].[动态排序值]; END SCOPE;
内容的提问来源于stack exchange,提问作者hamish inglis
相关产品推荐
相关产品推荐

