我有一种情况,我想查询多个属性(共8个)并包含小计。这是我想要的结果:
╔═══════╦═════════╦════════╦═════════╗
║ Attr1 ║ Attr2 ║ Attr3 ║ Measure ║
╠═══════╬═════════╬════════╬═════════╣
║ All ║ All ║ All ║ 50% ║
║ Foo ║ All ║ All ║ 25% ║
║ Bar ║ All ║ All ║ 90% ║
║ Foo ║ Anna ║ All ║ 42% ║
║ Foo ║ Brian ║ All ║ 12% ║
║ Bar ║ Charles ║ All ║ 10% ║
║ Bar ║ Dory ║ All ║ 112% ║
║ Foo ║ Anna ║ Box ║ 58% ║
║ Foo ║ Anna ║ Circle ║ 13% ║
║ ... ║ ... ║ ... ║ ... ║
╚═══════╩═════════╩════════╩═════════╝
现在,我几乎可以通过做这样的事情到达那里:
select
{[Measures].[Measure]} on columns,
nonempty({
[Dim1].[Attr1].allmembers *
[Dim2].[Attr2].allmembers *
[Dim3].[Attr3].allmembers
}) on rows
from [Cube]
然而,这当然给我一个包含如下成员的集合:
╔═══════╦═════════╦════════╦═════════╗
║ Attr1 ║ Attr2 ║ Attr3 ║ Measure ║
╠═══════╬═════════╬════════╬═════════╣
║ Foo ║ All ║ Box ║ 25% ║
║ Bar ║ All ║ Circle ║ 90% ║
║ Foo ║ Anna ║ Box ║ 16% ║
║ Bar ║ Charles ║ Circle ║ 78% ║
║ ... ║ ... ║ ... ║ ... ║
╚═══════╩═════════╩════════╩═════════╝
我不想要的东西 - 我可以和他们一起生活,除了8个维度之外它会让交叉连接变得有点疯狂(它让我有一个关于拥有超过40亿元组的错误的错误它...)。现在,如果我正在编写SQL,我可以做一些简单的事情:
select
Dim1.Attr1,
Dim2.Attr2,
Dim3.Attr3,
Sum(Measures.Measure) as Measure
group by
Dim1.Attr1,
Dim2.Attr2,
Dim3.Attr3
with rollup
但是我找不到在MDX中重现这个的简单方法。我可以使用以下内容手动构建每个汇总级别:
select
{[Measures].[Measure]} on columns,
nonempty(
{
{[Dim1].[Attr1].[All]} *
{[Dim2].[Attr2].[All]} *
{[Dim3].[Attr3].[All]}
} +
{
{[Dim1].[Attr1].[Attr1].allmembers} *
{[Dim2].[Attr2].[All]} *
{[Dim3].[Attr3].[All]}
} +
{
{[Dim1].[Attr1].[Attr1].allmembers} *
{[Dim2].[Attr2].[Attr2].allmembers} *
{[Dim3].[Attr3].[All]}
} +
{
{[Dim1].[Attr1].[Attr1].allmembers} *
{[Dim2].[Attr2].[Attr2].allmembers} *
{[Dim3].[Attr3].[Attr3].allmembers}
}
) on rows
from [Cube]
但是这已经变得单调乏味了三个维度 - 指定9组这些将是令人讨厌的。那么 - 有没有办法在MDX中简明扼要地做到这一点,或者我只需要使用长手解决方案?
就先前的研究而言,我遇到过像this one这样的答案,他们说使用WITH MEMBER
语句来创建一个总行 - 但这对我来说毫无意义,因为它结果在我试图用allmembers
函数避免的相同交叉连接行为中。
修改:这是代码的最新(已消毒)版本,包括@ Danylo对NonEmptyCrossJoin
的建议:
NON EMPTY {
NONEMPTYCROSSJOIN(
{[Dim1].[Attribute].[All]} *
{[Dim2].[Attribute].[All]} *
{[Dim3].[Attribute].[All]} *
{[Dim4].[Attribute].[All]} *
{[Dim6].[Attribute].[All]} *
{[Dim7].[Attribute].[All]} *
{[Dim8].[Attribute].[All]} *
{[Dim9].[Attribute].[All]} *
[Dim0].[Attribute].[Attribute].ALLMEMBERS
) +
NONEMPTYCROSSJOIN(
[Dim1].[Attribute].[Attribute].ALLMEMBERS *
{[Dim2].[Attribute].[All]} *
{[Dim3].[Attribute].[All]} *
{[Dim4].[Attribute].[All]} *
{[Dim6].[Attribute].[All]} *
{[Dim7].[Attribute].[All]} *
{[Dim8].[Attribute].[All]} *
{[Dim9].[Attribute].[All]} *
[Dim0].[Attribute].[Attribute].ALLMEMBERS
) +
NONEMPTYCROSSJOIN(
[Dim1].[Attribute].[Attribute].ALLMEMBERS *
[Dim2].[Attribute].[Attribute].ALLMEMBERS *
{[Dim3].[Attribute].[All]} *
{[Dim4].[Attribute].[All]} *
{[Dim6].[Attribute].[All]} *
{[Dim7].[Attribute].[All]} *
{[Dim8].[Attribute].[All]} *
{[Dim9].[Attribute].[All]} *
[Dim0].[Attribute].[Attribute].ALLMEMBERS
) +
...
}
答案 0 :(得分:2)
加速这种类型的MDX的一种方法是不要一步到位。 SQL也是如此。使用子立方体。
CREATE SUBCUBE [CubeName] AS
SELECT {SomeMeasures} ON COLUMNS,
{
CROSSJOIN({Field1.ALLMEMBERS},
{Field2.ALLMEMBERS},
More as needed
) }
ON ROWS
FROM [CubeName]
相当古怪,SubCube应该与您正在使用的立方体/透视图具有相同的名称。
您可以根据需要创建任意数量的子多维数据集,它们都具有相同的名称,然后从缩小的多维数据集中执行最终的SELECT语句。
之后放下子立方体。
答案 1 :(得分:1)
我无法看到使用至少一个交叉连接的方法(尽管将您感兴趣的度量放入NonEmpty()函数中 - 请参阅注释 - 可能有助于交叉连接性能/内存不足问题)。
SQL ROLLUP样式的总计根据GROUP BY子句中列的顺序排除ALL和非ALL的某些组合。 (在您的示例中,此排除在结果集中显示为ALL的整齐三角形图案)。 MDX不会这样做:它并不真正关心交叉连接中集合的顺序。
通过让MDX了解此订单,可以做到这一点。它有点复杂,但可能比长期的,#34; handbuilt"更容易(或表现更好)。你试过的方法:
WITH
MEMBER Measures.DimensionsAllPattern AS
CASE WHEN [Dimension1].[Hierarchy].CurrentMember.Properties("LEVEL_NUMBER")="0" THEN "1" ELSE "0" END +
CASE WHEN [Dimension2].[Hierarchy].CurrentMember.Properties("LEVEL_NUMBER")="0" THEN "1" ELSE "0" END +
CASE WHEN [Dimension3].[Hierarchy].CurrentMember.Properties("LEVEL_NUMBER")="0" THEN "1" ELSE "0" END +
... etc up to dimension 8...
MEMBER AllPatternStrNum AS VBA!Cstr(VBA!CLng(Measures.DimensionsAllPattern))
SELECT
{Measures.DimensionsAllPattern,Measures.AllPatternStrNum} ON 0,
FILTER
(CROSSJOIN
([Dimension1].[Hierarchy].AllMembers,
[Dimension2].[Hierarchy].AllMembers,
.... etc
)
,
(Measures.AllPatternStrNum="0") OR
(Measures.AllPatternStrNum=VBA!String(VBA!Len(Measures.AllPatternStrNum),"1"))
)
ON 1
FROM TheCube
这是做什么的:
对于维度中每个成员组合,根据指定的维度顺序构建与“全部/非全部”模式对应的字符串。例如,{All,Something,All,Something}将被编码为1010。
第二个计算成员将此度量转换为数字然后返回字符串:因此1010最终将为1010,但0011最终将为11(剥离前导零的简单方法)
然后根据该第二个成员过滤交叉连接组。它必须等于0(根本没有所有值),或者是一个1s的字符串,只要它自己的长度。
(注意我没有包含我的示例中的任何NonEmpty内容,或者您实际想要查看的内容)。
您可能需要将过滤后的集合包装在ORDER(set,something,BASC)中,以使其看起来像您想要的那样。
答案 2 :(得分:1)
我最近发布了一篇关于此的文章。为了避免交叉连接内存问题,我建议使用NonEmptyCrossJoin
函数包装集合。在此处阅读更多内容:http://blog.soft-prestidigitation.com/the-totals-and-the-nonemptycrossjoin-function.html