Selbst nach mehreren Jahren MDX kommt es immer mal wieder vor, dass man eine Funktion oder ein Statement noch nie gehört oder zumindest noch nie benutzt hat. So ging mir das vor kurzem, als ich das erste mal den Ausdruck HAVING in einer MDX Query gesehen habe, einen alten Bekannten aus der Abfragesprache SQL.

Grundsätzlich ist HAVING (gibt es seit SQL Server 2005) eine einfacher lesbare Alternative zum Filter. Interessantester Unterschied ist aber der Kontext in dem es ausgeführt wird.

(Details für Interessierte: http://www.databasejournal.com/features/mssql/article.php/3662721/MDX-Clauses-and-Keywords-Use-HAVING-to-Filter-an-Axis.htm)

Wie im SQL ist es nämlich die letzte Anweisung, die ausgeführt wird, wodurch es in bestimmten Situationen dramatisch schneller ist als der FILTER.

Ich denke eines der besten Einsatzgebiete könnte sein, wenn ich die zurückgegebenen Zeilen nach einer sehr komplexen Kalkulation filtern will, die ich aber gar nicht ausgeben möchte. Dieses Szenario habe ich in den nächsten beiden Abfragen mal versucht anhand des berechneten Elements „Teuer“ zu simulieren.

Abfrage mit FILTER

WITH
MEMBER Teuer AS AVG([Geography].[City].[City].MEMBERS,AVG([Date].[Date].[Date].MEMBERS
, [Measures].[Internet Order Count]
/([Measures].[Internet Order Count],[Date].[Date].[All Periods])
))
SELECT {[Measures].[Internet Sales Amount]} ON 0,
NONEMPTY{
FILTER([Customer].[Customer].[Customer].MEMBERS
, [Measures].[Internet Gross Profit] > 0
AND Teuer>0.25)
}
ON 1
FROM [Adventure Works]
WHERE (
[Customer].[Customer Geography].[Country].&[Germany]
)

Abfrage mit HAVING

WITH
MEMBER Teuer ASAVG([Geography].[City].[City].MEMBERS,AVG([Date].[Date].[Date].MEMBERS
, [Measures].[Internet Order Count]
/([Measures].[Internet Order Count],[Date].[Date].[All Periods])
))
SELECT {[Measures].[Internet Sales Amount]} ON 0,
NONEMPTY{
[Customer].[Customer].[Customer].MEMBERS
}
HAVING [Measures].[Internet Gross Profit] > 0
AND Teuer>0.25
ON 1
FROM [Adventure Works]
WHERE (
[Customer].[Customer Geography].[Country].&[Germany]
)

<?xml:namespace prefix = o />

Beide Abfragen liefern exakt das gleiche Ergebnis. FILTER benötigt für die 1747 Zeilen ca. 40 Sekunden. HAVING benötigt 4 (vier!).