如何在 Power BI 桌面中参数化聚合列?
How to parameterize a column for aggregation in Power BI desktop?
我有一些用户希望能够修改 table 聚合的列。我的问题是我似乎无法在 Power BI 中执行此操作。我基本上希望能够在 SQL:
中执行以下操作
SELECT
<OrgLevel1>,
<OrgLevel2>,
SUM([Revenue])
FROM [Data]
GROUP BY
<OrgLevel1>,
<OrgLevel2>
;
用户可以将 <OrgLevel1>
and/or <OrgLevel2>
更改为 { "(All)"
, [Department]
, [Product]
} 中的任何一个。
这里有一个 link 工作簿来说明这个问题,TestParameterizeGroupby.pbix(由 Google 云端硬盘托管)。我还在下面的屏幕截图中包含了字段定义。感谢您的帮助。
TestParameterizeGroupby.pbix
Link:TestParameterizeGroupby.pbix(由 Google 驱动器托管)
问题
[Org Level 1]
和 [Org Level 2]
字段不会根据用户的选择重新计算。仅显示默认值。
预期结果 table
"Org Level 1", "Org Level 2", "Revenue"
"(All)", "(All)", 28
备注
目的是拥有可参数化的组织级别字段,以便报表用户可以按所有、部门、产品或两者按任一顺序进行汇总。
Table 和列定义
'Data' = DATATABLE(
"Department",
STRING,
"Product",
STRING,
"Revenue",
DOUBLE,
{
{"DeptA", "ProdX", 5.0},
{"DeptA", "ProdY", 6.0},
{"DeptB", "ProdX", 10.0},
{"DeptB", "ProdY", 7.0}
}
)
'Data'[Org Level 1] = SWITCH(
'Org Level 1 Parameter'[Org Level 1 Parameter Value],
0,
"(All)",
1,
[Department],
2,
[Product]
)
// Problem: [Org Level 1] and [Org Level 2] fields are not recalculating from the users' selection. Only the default values are shown.
'Org Level 1' = DATATABLE(
"Org Level 1",
STRING,
"Org Level 1 Parameter",
INTEGER,
{
{"(0) (All)", 0},
{"(1) Department", 1},
{"(2) Product", 2}
}
)
'Org Level 1 Parameter'[Org Level 1 Parameter] = GENERATESERIES(0, 2, 1)
'Org Level 1 Parameter'[Org Level 1 Parameter Value] = SELECTEDVALUE('Org Level 1 Parameter'[Org Level 1 Parameter], 1)
Table 'Org Level 1' 与 [组织级别 1 参数] 列上的 'Org Level 1 Parameter' 具有 1-1 关系。
用户通过选择 'Org Level 1'[组织级别 1] 的值来选择 'Data'[组织级别 1] 的值。
Table[组织级别 2] 的列和列的定义方式与 [组织级别 1] 相同。
截图
报告视图:
数据查看:
模型视图:
Power BI 论坛中对 post 的交叉引用:
Power BI Forum: How to parameterize a column for aggregation
对此的一种解决方案是添加两个列表值参数并在 Power Query M 代码中使用它们的值来修改数据库查询。假设您有一个包含 Department
、Product
和 Revenue
列的 table Data
。为简单起见,我将再添加一列,命名为 Dummy Column
,所有行都具有相同的值(例如 null
)。我将在稍后解释原因post。所以 table 看起来像这样:
然后在您的报告中指定一个查询,将此 table 添加到您的模型(假设我们将导入它,但通常您也可以在 DirectQuery 中执行此操作):
现在,如果您查看 M 代码,您会在那里看到上面的查询:
Source = Sql.Database(".", "Whosebug", [Query=" select ....
现在定义几个参数,最终用户可以使用这些参数 select 如何聚合数据。让我们将它们命名为 Level 1
和 Level 2
:
参数的值可以通过参数名在M中使用,&
用于拼接字符串。因此,如果存在值为 Samuel
的参数 Name
,则表达式 "Hello, " & Name & "!"
将被计算为 Hello, Samuel!
。这个想法是检查我们参数的值并相应地修改数据库查询。
在 select 部分,我们将替换字段的名称 selected,或者我们将在 <All>
的情况下放置 ''
(空字符串) (我用括号将参数值括起来,以便更容易将参数值与数据库字段名称区分开来)。所以表达式应该是这样的:
"select " & (if #"Level 1" = "<Department>" then "Department" else ..." (and so on)
因为我们的参数名中有一个space,我们需要用#"
和"
将它包围起来,所以Level1
可以简单地引用为Level1
在代码中,但 Level 1
变为 #"Level 1"
.
按部分分组有点棘手。我们应该在字段名称之间添加一个逗号,添加或不添加字段名称,甚至完全省略 group by
(以防两个参数都设置为 <All>
)。为了简化这一点,我添加了一个虚拟列,所有行都具有相同的值(例如 null
)并且始终按该列分组。这种构建 group by 子句的方式更简单——如果参数值不是 <All>
,我们应该添加 , fieldname
。所以代码可能如下所示:
"group by DummyColumn" & (if #"Level 1" = "<Department>" then ", Department" else ..." (and so on)
所以最后的M代码是这样的:
let
Source = Sql.Database(".", "Whosebug", [Query="select#(lf) " & (if #"Level 1" = "<Department>" then "Department" else if #"Level 1" = "<Product>" then "Product" else "''") & " as [Org Level 1]#(lf) , " & (if #"Level 2" = "<Department>" then "Department" else if #"Level 2" = "<Product>" then "Product" else "''") & " as [Org Level 2]#(lf) , SUM(Revenue) as Revenue#(lf)from Data#(lf)group by DummyColumn" & (if #"Level 1" = "<Department>" then ", Department" else if #"Level 1" = "<Product>" then ", Product" else "") & (if #"Level 2" = "<Department>" then ", Department" else if #"Level 2" = "<Product>" then ", Product" else "")])
in
Source
现在,最终用户可以通过单击 Edit Queries
-> Edit Parameters
:
来更改参数值
和select如何分组数据:
默认情况下,Power BI Desktop 会在执行特定查询时第一次警告您:
如果要关闭此功能,请转到 File
-> Options and settings
-> Options
-> (GLOBAL) Security
并确保 Require user approval for new native database queries
是未 selected:
当最终用户改变参数值时,数据也会改变,例如:
或:
等等...
当每个用户都有自己的 .pbix 文件副本时,此技巧在 Power BI Desktop 中效果很好。但是,如果您发布它,首先更改参数值不是很方便(您必须去 datasat 的设置),更重要的是,更改参数值会影响所有正在查看此报告的用户。您还可以使用它来修改 Power Query 编辑器生成的 Table.Group
语句,以防您想在 Power BI 中聚合数据,但更改数据库查询更容易、更灵活。
如果要为已发布报告的并发多用户场景启用此场景,可以使用切片器和 What-if parameters。不幸的是,What-if 参数可以是数字(您不能在那里定义值列表),因此您可以使用度量 "decode" 参数的 int 值并编写一些 DAX 代码以相应地执行不同的聚合。比较费工夫,但如果需要,也可以制作。
我有一些用户希望能够修改 table 聚合的列。我的问题是我似乎无法在 Power BI 中执行此操作。我基本上希望能够在 SQL:
中执行以下操作SELECT
<OrgLevel1>,
<OrgLevel2>,
SUM([Revenue])
FROM [Data]
GROUP BY
<OrgLevel1>,
<OrgLevel2>
;
用户可以将 <OrgLevel1>
and/or <OrgLevel2>
更改为 { "(All)"
, [Department]
, [Product]
} 中的任何一个。
这里有一个 link 工作簿来说明这个问题,TestParameterizeGroupby.pbix(由 Google 云端硬盘托管)。我还在下面的屏幕截图中包含了字段定义。感谢您的帮助。
TestParameterizeGroupby.pbix
Link:TestParameterizeGroupby.pbix(由 Google 驱动器托管)
问题
[Org Level 1]
和 [Org Level 2]
字段不会根据用户的选择重新计算。仅显示默认值。
预期结果 table
"Org Level 1", "Org Level 2", "Revenue"
"(All)", "(All)", 28
备注
目的是拥有可参数化的组织级别字段,以便报表用户可以按所有、部门、产品或两者按任一顺序进行汇总。
Table 和列定义
'Data' = DATATABLE(
"Department",
STRING,
"Product",
STRING,
"Revenue",
DOUBLE,
{
{"DeptA", "ProdX", 5.0},
{"DeptA", "ProdY", 6.0},
{"DeptB", "ProdX", 10.0},
{"DeptB", "ProdY", 7.0}
}
)
'Data'[Org Level 1] = SWITCH(
'Org Level 1 Parameter'[Org Level 1 Parameter Value],
0,
"(All)",
1,
[Department],
2,
[Product]
)
// Problem: [Org Level 1] and [Org Level 2] fields are not recalculating from the users' selection. Only the default values are shown.
'Org Level 1' = DATATABLE(
"Org Level 1",
STRING,
"Org Level 1 Parameter",
INTEGER,
{
{"(0) (All)", 0},
{"(1) Department", 1},
{"(2) Product", 2}
}
)
'Org Level 1 Parameter'[Org Level 1 Parameter] = GENERATESERIES(0, 2, 1)
'Org Level 1 Parameter'[Org Level 1 Parameter Value] = SELECTEDVALUE('Org Level 1 Parameter'[Org Level 1 Parameter], 1)
Table 'Org Level 1' 与 [组织级别 1 参数] 列上的 'Org Level 1 Parameter' 具有 1-1 关系。
用户通过选择 'Org Level 1'[组织级别 1] 的值来选择 'Data'[组织级别 1] 的值。
Table[组织级别 2] 的列和列的定义方式与 [组织级别 1] 相同。
截图
报告视图:
数据查看:
模型视图:
Power BI 论坛中对 post 的交叉引用: Power BI Forum: How to parameterize a column for aggregation
对此的一种解决方案是添加两个列表值参数并在 Power Query M 代码中使用它们的值来修改数据库查询。假设您有一个包含 Department
、Product
和 Revenue
列的 table Data
。为简单起见,我将再添加一列,命名为 Dummy Column
,所有行都具有相同的值(例如 null
)。我将在稍后解释原因post。所以 table 看起来像这样:
然后在您的报告中指定一个查询,将此 table 添加到您的模型(假设我们将导入它,但通常您也可以在 DirectQuery 中执行此操作):
现在,如果您查看 M 代码,您会在那里看到上面的查询:
Source = Sql.Database(".", "Whosebug", [Query=" select ....
现在定义几个参数,最终用户可以使用这些参数 select 如何聚合数据。让我们将它们命名为 Level 1
和 Level 2
:
参数的值可以通过参数名在M中使用,&
用于拼接字符串。因此,如果存在值为 Samuel
的参数 Name
,则表达式 "Hello, " & Name & "!"
将被计算为 Hello, Samuel!
。这个想法是检查我们参数的值并相应地修改数据库查询。
在 select 部分,我们将替换字段的名称 selected,或者我们将在 <All>
的情况下放置 ''
(空字符串) (我用括号将参数值括起来,以便更容易将参数值与数据库字段名称区分开来)。所以表达式应该是这样的:
"select " & (if #"Level 1" = "<Department>" then "Department" else ..." (and so on)
因为我们的参数名中有一个space,我们需要用#"
和"
将它包围起来,所以Level1
可以简单地引用为Level1
在代码中,但 Level 1
变为 #"Level 1"
.
按部分分组有点棘手。我们应该在字段名称之间添加一个逗号,添加或不添加字段名称,甚至完全省略 group by
(以防两个参数都设置为 <All>
)。为了简化这一点,我添加了一个虚拟列,所有行都具有相同的值(例如 null
)并且始终按该列分组。这种构建 group by 子句的方式更简单——如果参数值不是 <All>
,我们应该添加 , fieldname
。所以代码可能如下所示:
"group by DummyColumn" & (if #"Level 1" = "<Department>" then ", Department" else ..." (and so on)
所以最后的M代码是这样的:
let
Source = Sql.Database(".", "Whosebug", [Query="select#(lf) " & (if #"Level 1" = "<Department>" then "Department" else if #"Level 1" = "<Product>" then "Product" else "''") & " as [Org Level 1]#(lf) , " & (if #"Level 2" = "<Department>" then "Department" else if #"Level 2" = "<Product>" then "Product" else "''") & " as [Org Level 2]#(lf) , SUM(Revenue) as Revenue#(lf)from Data#(lf)group by DummyColumn" & (if #"Level 1" = "<Department>" then ", Department" else if #"Level 1" = "<Product>" then ", Product" else "") & (if #"Level 2" = "<Department>" then ", Department" else if #"Level 2" = "<Product>" then ", Product" else "")])
in
Source
现在,最终用户可以通过单击 Edit Queries
-> Edit Parameters
:
和select如何分组数据:
默认情况下,Power BI Desktop 会在执行特定查询时第一次警告您:
如果要关闭此功能,请转到 File
-> Options and settings
-> Options
-> (GLOBAL) Security
并确保 Require user approval for new native database queries
是未 selected:
当最终用户改变参数值时,数据也会改变,例如:
或:
等等...
当每个用户都有自己的 .pbix 文件副本时,此技巧在 Power BI Desktop 中效果很好。但是,如果您发布它,首先更改参数值不是很方便(您必须去 datasat 的设置),更重要的是,更改参数值会影响所有正在查看此报告的用户。您还可以使用它来修改 Power Query 编辑器生成的 Table.Group
语句,以防您想在 Power BI 中聚合数据,但更改数据库查询更容易、更灵活。
如果要为已发布报告的并发多用户场景启用此场景,可以使用切片器和 What-if parameters。不幸的是,What-if 参数可以是数字(您不能在那里定义值列表),因此您可以使用度量 "decode" 参数的 int 值并编写一些 DAX 代码以相应地执行不同的聚合。比较费工夫,但如果需要,也可以制作。