Skip to content

Commit f3a5c98

Browse files
committed
Fix to support composite key columns (GroupByColumns) in StatExtractor.
This update resolves an issue in StatExtractor where an error occurred during the extraction of relationship statistics when one of the columns in the relationship was part of a composite key (GroupByColumns). The error message was: "Column [] is part of composite key, but not all columns of the composite key are included in the expression or its dependent expression." This fix applies only to models with a compatibility level of 1200 or higher, as GroupByColumns is not available in levels 1100 and 1103.
1 parent 6122894 commit f3a5c98

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

src/Dax.Model.Extractor/StatExtractor.cs

+45-9
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ private void LoadRelationshipStatistics(int sampleRows = 0,bool analyzeDirectQue
9191
CALCULATETABLE (
9292
ROW(
9393
""RelationshipId"", {rel.Dmv1200RelationshipId},
94-
""MissingKeys"", DISTINCTCOUNT ( {EscapeColumnName(rel.FromColumn)} ),
94+
""MissingKeys"", {DistinctCountExpression(rel.FromColumn)},
9595
""InvalidRows"", COUNTROWS({EscapeTableName(rel.FromColumn.Table)})
9696
),
97-
ISBLANK( {EscapeColumnName(rel.ToColumn)} ),
97+
{IsBlankExpression(rel.ToColumn)},
9898
USERELATIONSHIP( {EscapeColumnName(rel.FromColumn)}, {EscapeColumnName(rel.ToColumn)} )
9999
)").ToArray());
100100
// ""Column"", ""{EmbedNameInString(rel.FromColumn.ColumnName.Name)}"",
@@ -138,11 +138,11 @@ private void LoadRelationshipStatistics(int sampleRows = 0,bool analyzeDirectQue
138138
relationshipSet.Select(rel => (rel.MissingKeys > sampleRows && rel.MissingKeys <= MAX_KEYS_FOR_SAMPLE) ?
139139
$@"CALCULATETABLE (
140140
SELECTCOLUMNS (
141-
SAMPLE ( {sampleRows}, DISTINCT ( {EscapeColumnName(rel.FromColumn)} ), {EscapeColumnName(rel.FromColumn)}, ASC ),
141+
SAMPLE ( {sampleRows}, {DistinctExpression(rel.FromColumn)}, {EscapeColumnName(rel.FromColumn)}, ASC ),
142142
""RelationshipId"", {rel.Dmv1200RelationshipId},
143143
""MissingValue"", {EscapeColumnName(rel.FromColumn)}
144144
),
145-
ISBLANK( {EscapeColumnName(rel.ToColumn)} ),
145+
{IsBlankExpression(rel.ToColumn)},
146146
USERELATIONSHIP( {EscapeColumnName(rel.FromColumn)}, {EscapeColumnName(rel.ToColumn)} )
147147
)"
148148
: (DaxModel.CompatibilityLevel >= 1200) ?
@@ -155,7 +155,7 @@ private void LoadRelationshipStatistics(int sampleRows = 0,bool analyzeDirectQue
155155
""RelationshipId"", {rel.Dmv1200RelationshipId},
156156
""MissingValue"", {EscapeColumnName(rel.FromColumn)}
157157
))),
158-
ISBLANK( {EscapeColumnName(rel.ToColumn)} ),
158+
{IsBlankExpression(rel.ToColumn)},
159159
USERELATIONSHIP( {EscapeColumnName(rel.FromColumn)}, {EscapeColumnName(rel.ToColumn)} )
160160
)"
161161
:
@@ -237,15 +237,51 @@ private static string EscapeTableName(Table table)
237237

238238
private static string DistinctCountExpression(Column column)
239239
{
240-
// We always use COUNTROWS(ALLNOBLANKROW(t[c])) instead of DISTINCTCOUNT(t[c]) because it is compatible with GroupByColumns settings, such as Fields Parameters.
241-
// COUNTROWS(ALLNOBLANKROW()) always reads the list of values from the attribute hierarchy (when AvailableInMDX=true) or queries the table if the hierarchy is not available (when AvailableInMDX=false)
240+
var columnName = EscapeColumnName(column);
241+
242+
if (column.GroupByColumns.Count == 0) {
243+
return $"DISTINCTCOUNT({columnName})";
244+
}
245+
else {
246+
// COUNTROWS(ALLNOBLANKROW(t[c])) is compatible with GroupByColumns settings like Fields Parameters because it always retrieves the list of
247+
// values from the attribute hierarchy (when AvailableInMDX=true), or queries the table if the hierarchy is unavailable (AvailableInMDX=false).
248+
return $"COUNTROWS(ALLNOBLANKROW({columnName}))";
249+
}
250+
}
251+
252+
private static string DistinctExpression(Column column)
253+
{
254+
var columnName = EscapeColumnName(column);
242255

243-
return $"COUNTROWS(ALLNOBLANKROW({EscapeColumnName(column)}))";
256+
if (column.GroupByColumns.Count == 0) {
257+
return $"DISTINCT({columnName})";
258+
}
259+
else {
260+
var groupingColumnNames = string.Join(", ", column.GroupByColumns.Select((cn) => EscapeColumnName(column.Table, cn)));
261+
var tableName = EscapeTableName(column.Table);
262+
return $"DISTINCT(SELECTCOLUMNS(SUMMARIZE({tableName}, {columnName}, {groupingColumnNames}), {columnName}))";
263+
}
244264
}
245265

266+
private static string IsBlankExpression(Column column)
267+
{
268+
var columnName = EscapeColumnName(column);
269+
270+
if (column.GroupByColumns.Count == 0) {
271+
return $"ISBLANK({columnName})";
272+
}
273+
else {
274+
var groupingColumnNames = string.Join(", ", column.GroupByColumns.Select((cn) => EscapeColumnName(column.Table, cn)));
275+
return $"FILTER(ALL({columnName}, {groupingColumnNames}), ISBLANK({columnName}))";
276+
}
277+
}
246278
private static string EscapeColumnName(Column column)
247279
{
248-
return $"{EscapeTableName(column.Table)}[{column.ColumnName.Name.Replace("]", "]]")}]";
280+
return EscapeColumnName(column.Table, column.ColumnName);
281+
}
282+
private static string EscapeColumnName(Table table, DaxName columnName)
283+
{
284+
return $"{EscapeTableName(table)}[{columnName.Name.Replace("]", "]]")}]";
249285
}
250286
private static string EmbedNameInString(string originalName)
251287
{

0 commit comments

Comments
 (0)