SELECT 0 AS KeyColumn, ‘Bucket 0’ AS NameColumn
UNION ALL
SELECT 1 AS KeyColumn, ‘Bucket 1’ AS NameColumn
UNION ALL
SELECT 2 AS KeyColumn, ‘Bucket 2’ AS NameColumn
UNION ALL
SELECT 3 AS KeyColumn, ‘Bucket 3’ AS NameColumn
UNION ALL
SELECT 4 AS KeyColumn, ‘Bucket 4’ AS NameColumn
UNION ALL
SELECT 5 AS KeyColumn, ‘Bucket 5’ AS NameColumn
UNION ALL
SELECT 6 AS KeyColumn, ‘Bucket 6’ AS NameColumn
UNION ALL
SELECT 7 AS KeyColumn, ‘Bucket 7’ AS NameColumn
UNION ALL
SELECT 8 AS KeyColumn, ‘Bucket 8’ AS NameColumn
UNION ALL
SELECT 9 AS KeyColumn, ‘Bucket 9’ AS NameColumn
UNION ALL
SELECT 10 AS KeyColumn, ‘Bucket 10’ AS NameColumn
Create
Member CurrentCube.[Measures].[Weighted Discount Buckets] As
Int( [Measures].[Discount Amount] /
[Measures].[Reseller Sales Amount] * 10 )
, Format_String = ‘#,##0’
, Associated_Measure_Group = ‘Reseller Sales’
, Display_Folder = ‘WA’;
Scope
(
[Bucket].[Bucket].[Bucket].MEMBERS
);
This = Aggregate( Existing [Promotion].[Promotion].[Promotion].MEMBERS,
iif( [Bucket].[Bucket].CurrentMember.MemberValue =
(
[Measures].[Weighted Discount Buckets],
[Bucket].[Bucket].[All]
),
(
[Measures].CurrentMember,
[Bucket].[Bucket].[All]
),
null
)
);
End Scope;
select
PromotionKey, UnitPriceDiscountPct
from dbo.FactResellerSales
group by PromotionKey, UnitPriceDiscountPct
order by PromotionKey, UnitPriceDiscountPct
select PromotionKey, UnitPriceDiscountPct
from dbo.FactInternetSales
group by PromotionKey, UnitPriceDiscountPct
order by PromotionKey, UnitPriceDiscountPct
Our buckets will be discount percentages, grouped in bands of ten (0-9 = 0, 10-19 = 1, … 91 – 100 = 10). All together, we need 10 members in our utility dimension and that’s what initial named query does.
Since that dimension is not linked to any measure group, by bringing it in cube browser, we only see the same values per each member – total values. In order to have correct values per each member, we need to reach for MDX script and write proper expressions. The important thing to notice is that expressions should be written before any other statement in MDX script in order to allow all calculated measures (that follow) to be aggregated the way they’re suppose to (after our scope!). What once was solve order, is now the order of statements in MDX script.
The first thing we do is we define our calculated measure that will be used to determine buckets. It’s the same definition as in [Measures].[Discount Percentage] calculated measure, except we rounded the values and grouped them in 10 buckets. That measure can later be made hidden, if wanted so.
The following scope handles how each bucket is to be calculated per any measure – as an aggregate of values across existing promotions where dimension bucket key is equal to bucket measure. That expression is actually our transformation of data, which allocates value on buckets. It’s sort of a projection of calculated bucket measure on bucket dimension. That’s how it can be visualized and understood. Inside, it is important to refer to the root member of bucket dimension, because it’s the only member that has data before transformations get applied. That’s why we used tuples.
CONCLUSION
We reached the end of this article. Let’s summarize it one more time.
It is possible to make analysis of cube data based on dynamically calculated measure/buckets. The solution is to build an utility dimension with predetermined number of members (buckets) and then assign a value for each bucket. Values are assigned using scope statement where the key of the bucket is compared to the value of the calculation (calculated bucket measure). Effectively, that is a transformation of data from a measure to a dimension. Speaking of which, what better way to finish this article than to provide a vivid example.
We all love music and have our favorite media player, either a device or an application on a computer. Small and simple ones provide only basic operations like Play, Pause, etc. The other, more advanced feature multimedia database (music catalog, tracking the number of times a song is being played) and visualization (spectrum analyzer) among other things.
Last time we’ve focused on PlayedCount field, that is, on the frequency of occurence of an event (a song being played). A histogram of that data would show how many songs (height of a vertical bar) have been played each number of times (points on x axis). Not a very interesting thing, right? A drill-down/drill-through on top of that would be more interesting (which songs are played N times). But there wouldn’t be drill if it weren’t for histogram in the first place, to separate the data. Therefore, histograms are important, although not always used as the final result.
In this article, we’ve focused on the visualization. Spectrum analyzer to be precise. Those small panels where several vertical bands show how loud the bass, middle and treble are. Or more bands, depending on the number of them it displays (i.e. 100 Hz, 300 kHz, 1 KHz, 3 kHz, 10 kHz). Bands are ranges of frequency which display the amplitude for any given part of a song.
Well, did you know that a song can also be considered a small fact? The amplitude in that case is the measure. Dimensions? Well, there’s a Time dimension for sure. Others? Not likely. What about the Frequency dimension? Doesn’t exist there. It is however required to be present in the end result. How come? Well, bands are nothing but buckets of frequency range, where the number of them is predetermined in advance. The only thing that’s missing is the calculation that projects the amplitude across buckets in spectrum analyzer. Ring a bell?
FFT (Fast Fourier Transformation). How about it ?