【问题标题】:how to calculate average when some rows does not exist?当某些行不存在时如何计算平均值?
【发布时间】:2015-10-20 15:04:46
【问题描述】:

当某些值为 NULL 时,请帮助创建平均值

事实表:

立方体:

SELECT NON EMPTY {[Measures].[Score]} * [Date].[Month].allmembers ON COLUMNS
,{[Name].[name].allmembers} ON ROWS
FROM Test

问题:

当我计算平均值时,NULL 值被排除在外。我尝试了 COALESCEEMPTY(),但无论如何都无法正确计算平均值。分数 = 0 不正确的月份的平均值。代码如下:

WITH
MEMBER [Measures].[DateCount] AS DISTINCTCOUNT([Data].[date].[date])
MEMBER [Measures].[ScoreX] AS COALESCEEMPTY([Measures].[Score],0)
MEMBER [Measures].[DateCountX] AS COALESCEEMPTY([Measures].[DateCount],0)
MEMBER [Measures].[AvgScore] AS IIF([Measures].[DateCountX]=0,0,[Measures].[ScoreX]/[Measures].[DateCountX])
 SELECT NON EMPTY {[Measures].[AvgScore]} * [Date].[Month].allmembers ON COLUMNS
 ,{[Name].[name].allmembers} ON ROWS
 FROM Test

请帮助找到解决方案。

【问题讨论】:

  • 您需要使用 COALESCE_EMPTY 将空单元格替换为零。
  • 我添加了 COALESCEEMPTY,现在表格没有空单元格,而是 0。然而,“总分”是一样的。我怎样才能让它计算出正确的值?
  • 你是如何计算[数据计数]的?我在你的事实表中没有看到它。在我看来你在追求:(Score1 + Score2)/2,我不知道 [Data Count] 是如何进入它的。
  • 我更新了问题,详细说明了我如何获得 [Data Count]
  • 好的,那么你不能除以DataCount,或者当事实表中没有一个月份的行时,你仍然会除以1。您需要除以返回数据的月数。

标签: sql-server ssas mdx olap


【解决方案1】:

可能类似于以下内容:

WITH 
MEMBER [Measures].[Score X] AS
  IIF(
    [Measures].[Data Count]=0
    ,0
    ,[Measures].[Data Count]
  )
MEMBER [Measures].[Data Count X] AS
  COUNT(
    [name].[name].CURRENTMEMBER
    *[Measures].[Score X]
  )
MEMBER [Measures].[Avg Score] AS
  DIVIDE(
    [Measures].[Score]
   ,[Measures].[Data Count X]
  )
...
...

正如 Tab 提到的,您可以将函数 COALESCEEMPTY 用于上面的第一个计算成员:

WITH 
MEMBER [Measures].[Score X] AS
  COALESCEEMPTY(
    [Measures].[Data Count]
    ,0)
MEMBER [Measures].[Data Count X] AS
  COUNT(
    [name].[name].CURRENTMEMBER
    *[Measures].[Score X]
  )
MEMBER [Measures].[Avg Score] AS
  DIVIDE(
    [Measures].[Score]
   ,[Measures].[Data Count X]
  )
...
...

【讨论】:

  • 感谢您的回答。我不明白你使用的变量。第二个 MEMBER 语句中是否有一些错误输入? [Data Count] 在第一条语句中用于添加零并创建 [Score X]。在第二条语句中,创建了 [Data Count] 并使用了 [Score X]。请检查这是否正确?
  • -是的-让我再添加几个“X”
  • 请解释第二个陈述。当我实施它时,我得到#VALUE!到处
  • DIVIDE() 函数是否会避免被零除?我从来没用过。
  • @TabAlleman 您可以使用另一个参数 + 它是最近的,因此可能比 / operator 更快
【解决方案2】:

最终的解决方案是这样的:

WITH

MEMBER Measures.[AvgScore] AS
Avg(
Descendants(
[Data].[Date].CurrentMember,
[Data].[Date].[Date]
),
coalesceempty(Measures.[Score],0)
)

 SELECT NON EMPTY {[Measures].[AvgScore]} * [Date].[Month].allmembers ON COLUMNS
 ,{[Name].[name].allmembers} ON ROWS

FROM Test

【讨论】:

  • (upped) 感谢发帖 - 我之前没有使用过coalesceempty
【解决方案3】:

您的事实表需要为缺少名称的每个月表示 0。您可以使用 common-table-expression 来做到这一点。

declare @facttable table(name varchar(10),date datetime,score int);

insert into @facttable(name,date,score)
values
    ('a1','2015/01/01',15),
    ('a2','2015/01/01',30),
    ('a3','2015/01/01',26),
    ('a1','2015/02/01',20),
    ('a3','2015/02/01',14),
    ('a4','2015/02/01',45),
    ('a5','2015/02/01',3)



;

with fact_cte as(

    select
        tDistinctNames.DistinctName AS Name,
        tDistinctDates.DistinctDate AS Date,
        ISNULL(t.Score,0) AS Score

    from 
        (select distinct name as DistinctName from @facttable) tDistinctNames
            cross join
        (select distinct date as DistinctDate from @facttable) tDistinctDates

            left outer join @facttable t on 
                t.name = tDistinctNames.DistinctName AND
                t.date = tDistinctDates.DistinctDate

)
select *
from fact_cte

结果是这样的:

Name    Date    Score
a1  2015-01-01 00:00:00.000 15
a2  2015-01-01 00:00:00.000 30
a3  2015-01-01 00:00:00.000 26
a4  2015-01-01 00:00:00.000 0
a5  2015-01-01 00:00:00.000 0
a1  2015-02-01 00:00:00.000 20
a2  2015-02-01 00:00:00.000 0
a3  2015-02-01 00:00:00.000 14
a4  2015-02-01 00:00:00.000 45
a5  2015-02-01 00:00:00.000 3

【讨论】:

  • 这是一个选项,但不是很可扩展。我想通过 mdx 在分析服务中找到解决方案是一条更好的路线。
  • 很确定 OP 正在寻找 MDX 解决方案。
猜你喜欢
  • 1970-01-01
  • 2016-10-02
  • 1970-01-01
  • 2016-03-20
  • 2019-08-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
  • 1970-01-01
相关资源
最近更新 更多