Calculate measure across different time dimension tange - ssas

I have a calculated measure [Measures].[Person Count] defined as DISTINCTCOUNT(Visits[Person ID]). Our fiscal year runs from July to June. I would like to pull a report showing, by fiscal month, both distinct person counts for that month as well as a running total. However, the running total also needs to take into account distinct values. Here is what I have that almost works:
WITH MEMBER [Measures].[Cumulative Person Count] AS
Sum(PeriodsToDate([Date].[Fiscal Calendar].[Fiscal Year],
[Date].[Fiscal Calendar].CurrentMember),
[Measures].[Person Count])
SELECT [Date].[Fiscal Calendar].[Month].MEMBERS ON COLUMNS,
{ [Measures].[Person Count],
[Measures].[Cumulative Person Count] } ON ROWS
FROM [Model]
WHERE [Date].[FiscalYear].&[2018]
This gives something like the following:
+-------------------------+-------+--------+-----------+...
| | July | August | September |...
+-------------------------+-------+--------+-----------+...
| Person Count | 34268 | 37270 | 35971 |...
| Cumulative Person Count | 34268 | 71538 | 107509 |...
+-------------------------+-------+--------+-----------+...
The "Person Count" numbers are correct. The "Cumulative Person Count", however, is merely summing up the totals from each month, ignorant of the duplicates. Suppose that only 10% of person records are new each month. The result I would like to see would be something like the following:
+-------------------------+-------+--------+-----------+...
| | July | August | September |...
+-------------------------+-------+--------+-----------+...
| Person Count | 34268 | 37270 | 35971 |...
| Cumulative Person Count | 34268 | 37995 | 41592 |...
+-------------------------+-------+--------+-----------+...
What is the best way to reuse the [Measures].[Person Count] measure but apply it to a different range that is aware of the context?

You might just be using the incorrect aggregation type - try AGGREGATE instead:
WITH MEMBER [Measures].[Cumulative Person Count] AS
AGGREGATE(
PeriodsToDate(
[Date].[Fiscal Calendar].[Fiscal Year],
[Date].[Fiscal Calendar].CurrentMember),
[Measures].[Person Count]
)
An alternative to PeriodsToDate may be the use of NULL:..:
AGGREGATE(
{ NULL : [Date].[Fiscal Calendar].CurrentMember }
,[Measures].[Person Count]
)

Related

ParallelPeriod issues when time is not on axis

What's wrong with the calculated member [Amount LM] (=amount last month) in this query? It seems to work if I specify the time on rows but fails if I don't, even though I have a date in the where clause.
WITH
MEMBER [Amount LM] as
(
[Measures].[Amount],
ParallelPeriod (
[Date].[Year - Quarter - Month - Date - Hierarchy].[Year and Month],
1,
[Date].[Year - Quarter - Month - Date - Hierarchy].CurrentMember
)
)
SELECT
{[Amount LM], [Measures].[Amount]} ON COLUMNS,
[Measure Types].[Name].&[22] --not related to [Measures].[Amount]; Used as a measure switch in the real case but adjusted here for simplicity
-- comment out the next line to fail
* [Date].[Year - Quarter - Month - Date - Hierarchy].[Year and Month]
ON rows
FROM [Cube]
WHERE [Date].[Year Number].&[2019]
;
Result in the working case:
Amount LM | Amount
Costs | Jan 2019 | (null) | 109600
Costs | Feb 2019 | 109600 | 218300.5
Costs | Mar 2019 | 218300.5 | 392250
Costs | Apr 2019 | 392250 | 206800
Costs | May 2019 | 206800 | 174700
Costs | Jun 2019 | 174700 | 298400
Costs | Jul 2019 | 298400 | 264550
Costs | Aug 2019 | 264550 | 424100
Costs | Sep 2019 | 424100 | 129650
Costs | Oct 2019 | 129650 | 330050
Costs | Nov 2019 | 330050 | (null)
Costs | Dec 2019 | (null) | (null)
Without the
* [Date].[Year - Quarter - Month - Date - Hierarchy].[Year and Month]
part, Amount LM ist NULL
|Amount LM| Amount
Costs | (null) | 2548400.5
There is no issue with your calculation. To understand the Null you need to know
How ParallelPeriod works
How "CurrentMember" on a UserHierarchy works
When you have
"[Date].[Year - Quarter - Month - Date - Hierarchy].[Year and Month]"
in your row axis
"[Date].[Year - Quarter - Month - Date - Hierarchy].CurrentMember"
The above ".currentmember" expression returns the current member of the USER HIERARCHY "[Year - Quarter - Month - Date - Hierarchy]". The PARALLEL PERIOD function then tries to find the cousin member with respect to LEVEL "[Year and Month]".
When you remove the user hierarchy from rows , the currentmember returns 2019, which is a member of LEVEL "YEAR Number" hence the parallel period cannot find a cousin with respect to LEVEL "[Year and Month]"(since the passed currentmember is above the LEVEL specified). To check replace the year in the where with a month member(and no date on rows) it will work. To solve the issue , you need to provide an alternate logic incase if a higher level member is passed or other edge cases use the script below it will return 100 in any edge case .
WITH
MEMBER [Amount LM] as
case when [Date].[Year - Quarter - Month - Date - Hierarchy].CurrentMember.level.name <>"Year and Month" then 100
else
(
[Measures].[Amount],
ParallelPeriod (
[Date].[Year - Quarter - Month - Date - Hierarchy].[Year and Month],
1,
[Date].[Year - Quarter - Month - Date - Hierarchy].CurrentMember
)
)
end
Below is an example of your problem on Adventure works.
I have added two columns to check what ParallelPeriod and .currentmember are return
WITH
MEMBER [Amount LM] as
(
[Measures].[Internet Sales Amount],
ParallelPeriod ([Date].[Calendar].[Month],1,[Date].[Calendar].currentmember)
)
MEMBER [Amount LM_ParallelPeriodName] as
(
ParallelPeriod ([Date].[Calendar].[Month],1,[Date].[Calendar].currentmember).name
)
MEMBER [Amount LM_CalendarCurrentmember] as
(
[Date].[Calendar].currentmember.name
)
SELECT
{[Amount LM], [Measures].[Internet Sales Amount],[Amount LM_ParallelPeriodName],[Amount LM_CalendarCurrentmember]} ON COLUMNS,
[Product].[Category].&[1] * [Date].[Calendar].[Month]
ON rows
from [Adventure Works]
WHERE [Date].[Calendar Year].&[2013]
Result
Now Lets comment the
"[Date].[Calendar].[Month]"
WITH
MEMBER [Amount LM] as
(
[Measures].[Internet Sales Amount],
ParallelPeriod ([Date].[Calendar].[Month],1,[Date].[Calendar].currentmember)
)
MEMBER [Amount LM_ParallelPeriodName] as
(
ParallelPeriod ([Date].[Calendar].[Month],1,[Date].[Calendar].currentmember).name
)
MEMBER [Amount LM_CalendarCurrentmember] as
(
[Date].[Calendar].currentmember.name
)
SELECT
{[Amount LM], [Measures].[Internet Sales Amount],[Amount LM_ParallelPeriodName],[Amount LM_CalendarCurrentmember]} ON COLUMNS,
[Product].[Category].&[1] --* [Date].[Calendar].[Month]
ON rows
from [Adventure Works]
WHERE [Date].[Calendar Year].&[2013]
Result
Notice the Null returned by ParallelPeriod, Now lets replace the Year in where from Month. This enables paralellperiod to return something useful
WITH
MEMBER [Amount LM] as
(
[Measures].[Internet Sales Amount],
ParallelPeriod ([Date].[Calendar].[Month],1,[Date].[Calendar].currentmember)
)
MEMBER [Amount LM_ParallelPeriodName] as
(
ParallelPeriod ([Date].[Calendar].[Month],1,[Date].[Calendar].currentmember).name
)
MEMBER [Amount LM_CalendarCurrentmember] as
(
[Date].[Calendar].currentmember.name
)
SELECT
{[Amount LM], [Measures].[Internet Sales Amount],[Amount LM_ParallelPeriodName],[Amount LM_CalendarCurrentmember]} ON COLUMNS,
[Product].[Category].&[1] * [Date].[Calendar].[Month]
ON rows
from [Adventure Works]
WHERE [Date].[Month Name].[September 2013]
Result

Access Query - Sum of Field based on newest for each day

I have the following data:
Site # | Site Name | Product | Reading Date | Volume
1 | Cambridge | Regular | 02/21/17 08:00 | 40000
2 | Cambridge | Regular | 02/22/17 07:00 | 35000
3 | Cambridge | Regular | 02/22/17 10:00 | 30000
What I want to achieve is get the SUM of [Volume] of the last 30 days while taking the newest reading EACH day possible since its pretty inconsistent whether one day there are 1,2 or 3 readings. I have tried a couple of things but can't get it to work.
This is what I've tried:
SELECT [Site #], Product, Sum(Volume) AS SumOfVolume, DatePart("d",InventoryDate]) AS Day
FROM [Circle K New]
GROUP BY [Site #], Product, Day
HAVING (([Site #]=852446) AND (Product ="Diesel Lows"))
ORDER BY DatePart("d",[Inventory Date]) DESC;
Result:
It adds the two readings of the same day. I was/am thinking about just getting a daily average then finding the monthly average from that. But I'm unsure if the value changes affect average numbers.
Based on your description:
select sum(volume)
from data as d
where d.readingdate in (select min(d2.readingdate)
from data as d2
group by int(d2.readingdate)
) and
d.readingdate >= dateadd("d", -30, date());

MDX union members in different hierarchies

What I want is to create a query that shows members from two different hierarchies side-by-side on the same axis. For example, something like this:
-----------------------------------------------------------------
| | Product |
-----------------------------------------------------------------
| Location | Total Amount | Qty of Product A | Qty of Product B |
-----------------------------------------------------------------
| USA | 9,249.23 | 2,382 | 1,009 |
-----------------------------------------------------------------
| UK | 9,998.09 | 5,282 | 5,129 |
-----------------------------------------------------------------
It’s clear we can get the results we need by running two different queries, as follows:
select
[Measures].[Sales Amount] on 0,
[Country].[USA],[Country].[UK] on 1
from [Cube]
where [Time].[Year].[2010]
select
crossjoin([Product].[Type].members, [Measures].[Sales Quantity]) on 0,
[Country].[USA],[Country].[UK] on 1
from [Cube]
where [Time].[Year].[2010]
I found this post http://blog.crossjoin.co.uk/2009/05/20/joining-the-results-of-two-mdx-queries-together which is helpful but is a little bit different from my case.
How can I use MDX get result which has different hierarchies members in the same axises?
Maybe something like this:
SELECT
{
([Product].[Type].[All], [Measures].[Sales Amount])
,{[Product].[Type].members * [Measures].[Sales Quantity]}
} ON 0,
[Country].[USA],[Country].[UK] ON 1
FROM[Cube]
WHERE [Time].[Year].[2010];

MDX: Aggregate [Date].[Calendar].[Quarter] level to create new [Date].[Calendar].[Semi Annual] Level

I have a Date Dimension that has Month Hierarchy
Year -> Quarter -> Month -> Day -> Hour
I have two measures. Measure_A (Aggregation is Max), Measure_B (Aggregation is SUM)
I need to Multiply Measure_A by 24 on "Day" level then I need to SUM it Semi Annually.
Is it possible to create a new hierarchy by just using an MDX query? Below is the output that i am trying to achieve
Year | CY H1 | Measure_C | Measure_B
Where: Measure_C is the SUM of (Measure_A * 24) from January 1 to June 30, and CY H1 will be the new level.
I don't have any problem with Measure_B because its aggregation is SUM. Only with Measure_A beacause the aggregation is Max.
Is this possible to achieve without altering the cube, just do an MDX? Thanks.
Updated:
This is my query and output as of the moment,
Query:
With
MEMBER [Measures].[Measure_C] AS
SUM ( Descendants ( [Date].[Date Calendar], [Date].[Date Calendar].[Day]), [Measures].[Measure_A] * 24 )
, Format_String = "#,##0"
Select
{
[Measures].[Measure_C]
} ON Columns,
NON Empty
{
[Date].[Date Calendar].[Quarter].ALLMEMBERS
} ON Rows
From [Cube]
Output:
+------+---------+-----------+
| Year | Quarter | Measure_C |
+------+---------+-----------+
| 2011 | Q1 | 12 |
| 2011 | Q2 | 45 |
| 2011 | Q3 | 12 |
| 2011 | Q4 | 25 |
+------+---------+-----------+
What I am trying to do is to merge Q1 and Q2 to get Calendar Semester for the first half (CY H1)
Required output:
+------+---------+-----------+
| Year | Half Yr | Measure_C |
+------+---------+-----------+
| 2011 | CY H1 | 57 |
| 2011 | CY H2 | 37 |
+------+---------+-----------+
Please note that we don't have a natural Hierarchy for CY H1. But according to the comment below, this is not possible using mdx alone.
By the way, I am doing this for reporting services so I guess I will just do the magic in the presentation layer since this is not achievable using MDX query alone. :)
Assuming that your year 2011 is named [Date].[Date Calendar].[2011], then you can add calculated members as children of it like this:
With
MEMBER [Measures].[Measure_C] AS
Aggregate ( Descendants ( [Date].[Date Calendar], [Date].[Date Calendar].[Day]),
[Measures].[Measure_A] * 24
)
, Format_String = "#,##0"
MEMBER [Date].[Date Calendar].[2011].[CY H1] AS
Aggregate({ [Date].[Date Calendar].[Q1], [Date].[Date Calendar].[Q2] })
MEMBER [Date].[Date Calendar].[2011].[CY H2] AS
Aggregate({ [Date].[Date Calendar].[Q3], [Date].[Date Calendar].[Q4] })
Select
{
[Measures].[Measure_C]
} ON Columns,
NON Empty
{
[Date].[Date Calendar].[2011].[CY H1],
[Date].[Date Calendar].[2011].[CY H2]
} ON Rows
From [Cube]
You can try defining something like
With Member [Measures].[Measure C] as Sum( [Date].[2014].[1].[1].[1] : [Date].[2014].[2].[6].[30] ), [Measures].[Measure A] ) * 24
Alternatively, you can define it in a more flexible way, such as
Member [Measures].[Measure C pre] as Sum( Descendants( [Date].CurrentMember, [Date].[Day] ), [Measures].[Measure A] ),
which is the sum of the max of each day, but this is only valid for Date members that exist in the dimension (not calculated members). You will then need to explicitly calculate the aggregation using the same set of months or quarters you are using in your Rows clause.

MDX: Count number of days excluding weekends

I already had an MDX query that returns number of days in a Month Hierarchy using a calculated member. What I needed to do is to add new calculated member that returns number of days excluding weekends (Saturdays and Sundays).
Below is my existing MDX query using Adventure Works DW 2008R2 SE
WITH
MEMBER [Measures].[Num of Days] AS
COUNT (
Descendants ( [Date].[Calendar], [Date].[Calendar].[Date])
)
SELECT
{ [Measures].[Num of Days] } ON COLUMNS,
[Date].[Calendar].[Month].ALLMEMBERS ON ROWS
FROM [Adventure Works]
sample existing output:
+----------------+-------------+
| Month Year | Num of Days |
+----------------+-------------+
| July 2005 | 31 |
| August 2005 | 31 |
| September 2005 | 30 |
+----------------+-------------+
sample expected output:
+----------------+-------------+--------------------------------+
| Month Year | Num of Days | Num of Days Excluding Weekends |
+----------------+-------------+--------------------------------+
| July 2005 | 31 | 21 |
| August 2005 | 31 | 23 |
| September 2005 | 30 | 22 |
+----------------+-------------+--------------------------------+
The standard solution for this is to have a hierarchy in your time dimension with the days of the week ( Monday,... Sunday). Once you for this you can filter directly using those members. You can even do a hierarchy with just weekend/no weekend. The best solution depends on the measures you've in your schema, the best is always using standard MDX aggregations and avoiding using SUM/COUNT on a set of members.
Other solutions might depend on how you implemented your hierarchy, you can use the Weekday and filter function.
Honestly something like, I haven't check it
Count( FILTER( Descendants ( [Date].[Calendar], [Date].[Calendar].[Date]) , WeekDay( [Date].[Calendar].currentmember.properties("KEY"), 2) <= 5 ) )