MDX Calculated Member filter using attribute not working - sql

I have this setup:
ID T Date
2 T2 2022-11-18
3 T1 2022-11-21
and in the main fact table there are deals with ID 2 and 3.
Date is an attribute and appears, and works correctly, as a slicer in a pivot table in Excel. T is also an attribute, not visible, purely for the calculated members.
I created a Calculated Member and it doesn't work:
([Date].[T].&[T2], [Measures].[Notional_SUM])
However a check/test using ID does:
([Date].[ID].&[2], [Measures].[Notional_SUM])
obviously this works as 2 is actually in the fact table but what have I forgotten such that using T does not work?
I want to be able to use T as there'll always be T1 and T2 dates but I may not always know the ID (auto- generated by the SQL script rolling the dates).
***EDIT - After testing in Excel I realised that the one I thought does not work actually does if Date is removed from the slicer/top setup.
So obviously the top/slicer is a WHERE on just that date meaning my calculated member
([Date].[T].&[T2], [Measures].[Notional_SUM])
does not 'find' any T2 in the data it sees.
So how can I have a Calculated Member that always shows the T2 data?
I'm constructing an SSAS copy of an existing in-memory Java OLAP cube which does this and I have to ensure all dims/measures are the same.
Thanks
Leigh
tilleytech.com

it has been long long time since I wrote MDX, and as I do not have a running SSAS to debug your issue, I will try to dig the answer from my memory.
There is a difference between the use of &, which I believe is to be used on keys, and not on members. Try to use this:
([Date].[T].[T2], [Measures].[Notional_SUM])

So actually as I've not used SSAS before I'm still learning bits and I had not checked out the attribute relationship tab.
I used the attribute relationship tab to define that T is related to Date and not ID (the ID links to the fact tables).
Once this was done the behaviour now works and when Date is changed the T2 values, and move/diff calculated members, all work as expected.

Related

Add row number/rank to ssas tabular model

I'm trying to add row numbers (by some sorting column) or at least ranks into a calculated table inside azure analysis services tabular model (I need this rank column to use in TOPNSKIP, it should be precalculated column in the model's table. Really it will not be precalculated column for one sorting column only. It will be some expression I want to have precalculated). I used some thoughts from here DAX - Get current row number
I use Visual Studio with Microsoft Analysis Services Projects extension to deploy the model to ssas and SSMS to debug the requests. But it seems there are differences between dax requests in the SSMS and in the tabular models definitions.
The SSMS uses evaluate syntaxis and the tabular constructor = VAR RETURN. And it seems some functions are not available for the tabular models. It seems like ADDCOLUMNS and RANKX are not available for tabular models. Also , is used as operand separator in the SSMS and ; in the model DAX editor, (possible due to some internationalization options on my computer) and that is not very convenient. I could not find a way to get error report for the bad DAX request for the model definition. I only see for incorrect request that has been retrieved 0 records while I deploy a model and if I try to do some request to a table after deploying I get error message that it's empty because of incorrect construction, but no details. There is also a possibility to use calculated columns during the table construction, but I could not embed the RANKX function to the formula for them. Also I don't know how to use a MEASURE inside a construction function. The filter approach from the mentioned stackoverflow question was very slow on my amount of data. I was waiting about half an hour and stopped the deploying.
Because I don't see the ADDCOLUMNS works I've tried GENERATE and SELECTCOLUMNS. For example:
=
VAR NewTable = GENERATE(BaseTable; ROW("RowNumber"; RANKX(BaseTable; BaseTable[SortName];;1)))
RETURN NewTable
It works nice in the SSMS but can't be used to construct a table. While:
=
VAR NewTable = GENERATE(BaseTable; ROW("RowNumber"; 50))
RETURN NewTable
works fine everywhere. So I think RANKX is not working in the tabular model definitions.
Is there any way to rank or number rows in ssas calculated table by some sorting column?
Adding high cardinality columns such as an index number column is generally not advisable for tables in a tabular model, since these columns compress very very badly, thereby reducing query performance. Especially if the table is large. But if you must do it, use the technique shown here. If you don't want to add a calculated column to an existing table, you can wrap everything in a call to ADDCOLUMNS:
=
ADDCOLUMNS(
BaseTable,
VAR CurrentSortName = BaseTable[SortName]
RETURN
COUNTROWS(
FILTER(BaseTable, BaseTable[SortName] < CurrentSortName)
) + 1
)

Can someone explain the following Essbase code: FIX, #relative

Can someone please explain the below Essbase code to me please? This is my first time looking at any Essbase code and I'm getting a bit confused as to what it is actually doing.
FIX(&Mth, &Yr, &Version,
"Sector1","Sector2", #relative("Source Code",0), #relative("Channel", 0) )
FIX("AccountNo","DepNo")
DATACOPY "1A11"->"A-500" TO "1BCD"->"C-800";
ENDFIX
ENDFIX
From what I have googled the following is my understanding:
Creates a new command block which restricts database calculations to this subset.
Passes the following members into the command to be used:
Mth
Yr
Version
Returns the following fields:
Sector1
Sector2
returns the 0-level members of the Source Code member - meaning it returns the members of the Total Source Code without children (no other dimensions)
returns the 0-level members of the Channel member - meaning it returns the members of the Channel without children (no other dimensions)
Begins a new command block and passes the following members into the command to be used:
AccountNo
DepNo
Copies the range of cells 1A11, A-500 over to the range 1BCD, C-800
The above is what I understand from the oracle documents on each of the functions, but I can't actually figure out what is happening.
Welcome to the world of Essbase; it can be a little daunting at first especially if you're new to the concept of multidimensionality. You are on the right track regarding analyzing your calc script.
Try not to think of the FIX statement as a command block, per se. A FIX is used to select a portion of cells in the cube. Every single piece of data in your cube has a particular address that consists of one member from every dimension, plus the actual data value itself. For instance, a cube with the dimensions Time, Year, Scenario, and Location might have a particular piece of data at Jan->2018->Actual->Washington. The number of possible permutations of data in a cube can quickly get very large. For instance, if you're organization has 4 years of data, 12 months in a year, 100 locations, 10000 accounts, 3 versions, and 10 departments, you are talking about 4 * 12 * 100 * 10000 * 3 * 10 = 1.4 billion different potential addresses (cells) of data – and that's actually fairly small for a cube, as they tend to grow much larger.
That said, FIX statements are used to narrow down the scope of your calculation operation, rather than operating on the ENTIRE cube (all 1.4 billion cells in my hypothetical example), the FIX essentially restricts the calculation to cells that match certain criteria you specify. In this case, the first FIX statement restricts the calculation to a particular month, yr, version, sectors, sources, and channels. Note that the ampersand on Mth, Yr, and Version means that a substitution variable is to be used. This means your server or cube has a substitution variable value set, such as the variable Mth = "Jan" and Yr = "FY2018" and Version might be "Working" or "Final" or something similar. I would guess that Sector1 and Sector2 are possibly two different members from the same dimension. #RELATIVE("Source Code", 0) is a function that finds the level-0 members (leaf/bottom-level members in a dimension, that is, members that do not have children below them) of the specified member.
In other words, the first FIX statement is narrowing the scope of the calculation to a particular month in a particular year in a particular version (as opposed to all months, all years, all versions), and for that particular month/year/version (for either Sector1 or Sector2) it is fixing on all of the level-0/bottom/leaf members in Source Code and Channel dimensions.
The next FIX statement just further narrows the current scope of cells to calculate on in addition to the outer FIX. It's not uncommon to see FIX statements nested like this.
Lastly we get to the part where something actually happens: the DATACOPY. In the given FIX context, this DATACOPY command is saying that for EACH cell in the current FIX, copy values from the source to the destination. DATACOPY is a little more straightforward when it's just DATACOPY "Source" TO "Target" as opposed to using the inter dimensional operator (->)... but this is perhaps more easily understood in terms of the time/year dimensions. For example, imagine the data copy was written like this:
DATACOPY "FY2018"->"Dec" TO "FY2019"->"Jan";
In this DATACOPY I'd be telling Essbase that for the given FIX context I would like to copy values from the end of the year (data values where the year is FY2018 AND the month is Dec) to the beginning of the next year (data values where the year is FY2019 AND the month is Jan). Your DATACOPY is working in a similar fashion, but using cost centers or something else. It all just depends on how the cube is setup.

SQL - Need to find a way to check whether a member has renewed

So, this is probably simple. I need to find a way to check whether a member of a scheme has renewed their membership or let it expire, I need to generate a simple list of those whom have not renewed.... There are complicating factors however, in that I cant use Excel, and it can only be a single step to Crystal reports (though I have solved the issue in Excel using a simple Countifs and if Formula)
Now for the problem.
The membership has specified Start/End Dates in separate columns in the table. It is easy to see whether this, in a row basis has expired. The issue is that if they have renewed, this is logged as a separate table entry linked by a Individual reference to the member. There are also multiple Qualifications I also need to test against.
So, whilst I can test the expiration date, the question is how can I test against the rest of the data, based on whether the Individual Reference and Qualification name and then check whether this is "Current". Doing this would enable me to therefore test whether the Membership has therefore been renewed, or not, on an individual line.
Any advice on methods would be appreciated.
Without knowing what data you have and making assumptions out the wazoo, try something along these lines
select distinct Member_id,
case
when exists (select 1
from members m2
where m2.member_id = m1.member_id
and (m2.expiry_date is null
or m2.expiry_date > '2018-01-25'))
then 'Active'
else 'Expired'
end as mem_status
from members m1
What the exists does is look and see if that member has an active status

Use domain of one table for criteria in another in ms Access query?

I am trying to create a report that displays 3 different numbers for each of my projects.
Contract Hours - Stored in projects table, 1 to 1 relationship
Worked Hours - Stored in linked table that will be updated using an external website reporting feature that will contain only data for the dates that are to be displayed in the report, one to many relationship needs to be a sum
Allocated Hours - Stored in a table in my database called allocations and contains data for all dates, one to many relationship needs to be summed.
Right now i have it set up in a way that the user has to type the data range for the report every time it is run, however the date range only actually applies to the Allocation data because the worked hours data comes filtered and the contract data is one to one.
What I would like to do is set up a query that can see the domain of the worked hours and apply it as a date criteria for the allocated hours.
I have attempted to use max and min values of the Worked hours and tried to get creative but I'm actually not even sure if this is possible because I cannot see any simple solution (although I know it should be possible and fairly simple)
Any help, suggestions, or recommendations are appreciated.

MDX Calculated Member SubCube

I am relatively new to this depth of MDX, but here is my dilemma. My goal is to implement a calculated member using a .Net Stored Procedure. The calculation (XIRR) will be based on a set of cash flow dates and cash flow amounts. Ideally this would be a calculation in my cube that is available as a measure to Excel/Browser users.
So to start simple I am just trying to implement my own COUNT calculated member/measure (not even using .Net) to say count the # of members in a given dimensions based on the current context. So lets say I have a dimensions Customer with a Customer Id Key. And let's say there are a total of 100 customers in my database. So Count(Customer.CustomerId.AllMembers) would be 100. Now when you start using the browser and say filter on Customer.CustomerId.&1, Customer.CustomerId.&2 (customer id 1 and 2) I would expect my count calculated member to return 2 but it returns the total 100 count. I have tried using exists. I am sure there is something that I am just fundamentally not understanding yet.
Hopefully this makes sense, would hugely appreciate any help from someone that has a good understanding of SSAS/MDX and calculations. Thanks in advance.
Marty
You may have some issues here, I did when I tried to do a similar thing.
Your calculated member is not honouring the client sub-select, which is normal. What in theory you would do is create a dynamic set, and then use that in the calculated member to force the dimension count to be evaluated in the context of the subcube your filters have created. Mosha has a good article here: http://sqlblog.com/blogs/mosha/archive/2007/08/25/mdx-in-katmai-dynamic-named-sets.aspx
So you'd end up with something like:
CREATE DYNAMIC SET CurrentCube.Customers AS
EXISTING(Customer.CustomerId.CHILDREN);
CREATE MEMBER CurrentCube.Measures.CustomerCount AS
Customers.COUNT
Now the real problem you'll have is a bug in SSAS https://connect.microsoft.com/SQLServer/feedback/details/484865/calcuated-member-with-a-reference-to-dynamic-named-set-kills-the-cubes-performance so the code above, which will probably work just fine locally, will kill a production cube. This was an exciting learning experience for me.
See if you can get any of the workarounds to work, I couldn't.
I was able to get what I wanted, but I had to create query-scoped dynamic sets as part of the MDX query, I wasn't able to create it as a cube object:
WITH DYNAMIC SET Customers AS
EXISTING(Customer.CustomerId.CHILDREN);
MEMBER Measures.CustomerCount AS
Customers.COUNT
SELECT
Measures.CustomerCount
ON COLUMNS
FROM [Cube]
WHERE Customer.CustomerId.&[1]
Let us know how you get on.