How to dynamically change a dimension from within a Member Function (in MDX) - ssas

I've been having a hard time trying to figure out how to dynamically change a dimension from within a member function in MDX.
I have a fact table that contains 2 datetime fields (OperationDate and MeetingDate). I have a Power BI dashboard that has a date slicer which is based on the OperationDate. There's a matrix that has a summary of some measures (OpportunitiesCount, LostCount, WinCount, etc) that is being grouped by Sellers. Something like...
Date Slicer (this is based on OperationDate)
DateFrom: 2020-09-01
DateTo: 2020-09-30
<table>
<tr>
<th>SellerName</th>
<th>OpportunityCount</th>
<th>LostCount</th>
<th>WinCount</th>
<th>MeetingCount</th>
</tr>
<tr>
<td>SellerA</td>
<td>10</td>
<td>1</td>
<td>8</td>
<td>?</td>
</tr>
<tr>
<td>SellerB</td>
<td>12</td>
<td>0</td>
<td>2</td>
<td>?</td>
</tr>
<tr>
<td>SellerC</td>
<td>11</td>
<td>3</td>
<td>4</td>
<td>?</td>
</tr>
</table>
So the [OpportunityCount], [LostCount] and [WinCount] are based on OperationDate. The formulas for the first three columns are similar, but I'll take as an example the LostCount which goes somewhat like:
([Measures].[RowCount],[RowTypes].[Row Type].&[Lost])
At the UI level, the Date Slicer will do the math based on the OperationDate.
On the other hand, for the [Meeting] since it is based on MeetingDate, here's where I get stuck because I would think or thought that by borrowing the formula that I used for the first three columns it would be somewhat like:
([Measures].[RowCount],[RowTypes].[Row Type].&[Meeting])
But this would not give me the correct number since the Date Slicer is based on the OperationDate and not the MeetingDate.
Also I tried to create them from SSMS MDX editor as Member Functions but they are hard-coded. I would like them to be dynamic. In other words, at run-time if there's the possibility to swap dimensions (OperationDate and OptyMeetingDate).
Hardcoded way:
with MEMBER [Measures].[LostCountOperationDate] AS
sum(
(
[Measures].[RowCount]
,[RowTypes].[Row Type].&[Lost]
,([OperationDate].[FullYear].[Day].&[2020-09-01T00:00:00]:[OperationDate].[FullYear].[Day].&[2020-09-30T00:00:00])
)
)
MEMBER [Measures].[MeetingCountMeetingDate] AS
sum(
(
[Measures].[RowCount]
,[RowTypes].[Row Type].&[Meeting]
,([OptyMeetingDate].[FullYear].[Day].&[2020-09-01T00:00:00]:[OptyMeetingDate].[FullYear].[Day].&[2020-09-30T00:00:00])
)
)
QUESTION:
Is there a way to have something like...
with MEMBER [Measures].[RowCountOnAnyDateType] AS
sum(
(
[Measures].[RowCount]
,[RowTypes].[Row Type].&[Lost]
-- to have either dynamically OperationDate
,([OperationDate].[FullYear].[Day].&[2020-09-01T00:00:00]:[OperationDate].[FullYear].[Day].&[2020-09-30T00:00:00])
-- or OptyMeetingDate
,([OptyMeetingDate].[FullYear].[Day].&[2020-09-01T00:00:00]:[OptyMeetingDate].[FullYear].[Day].&[2020-09-30T00:00:00])
-- but has to be ONLY one of them based on the date range slicer selected at the UI
)
)
Thanks in advance,
Felix

Related

Calculated measure hurting performance and returning many more rows

I have the following query which should be returning income split by country and date. It should also be including a count of the number of dates in the grouping. This would be useful for a calculation looking at an entire month of income/days. I'm finding that the calculated measure is causing all countries in the dimension to be returned regardless of if there's any income data for it. Is there any way to limit this so only countries with income are returned?
with
MEMBER [Measures].[group_day_count] as
COUNT(
Descendants(
[Date].[Date].currentmember, [Date].[Date].[Date]
)
)
SELECT NON EMPTY Hierarchize({DrilldownLevel({[Date].[Date].[All]},,,INCLUDE_CALC_MEMBERS)})
DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME,
[Date].[Date].[Date].[Date Sort] ON COLUMNS ,
NON EMPTY CrossJoin(Hierarchize({DrilldownLevel({[Source Location].[Country Code].[All]},,,INCLUDE_CALC_MEMBERS)}),
{[Measures].[group_day_count],[Measures].[income]})
DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME ON ROWS
FROM (SELECT ({[Date].[Date].&[2017-10-04], [Date].[Date].&[2017-10-05], [Date].[Date].&[2017-10-06], [Date].[Date].&[2017-10-07], [Date].[Date].&[2017-10-08], [Date].[Date].&[2017-10-09], [Date].[Date].&[2017-10-10]})
ON COLUMNS FROM [Placeholder])
CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS
Try:
IIF([Measures].[Income],[Measures].[Days],NULL)

Join between 2 tables where date_field is between dates

I am struggling with how to achieve my desired outcome using SQL.
I have 2 tables that I am trying to join.
Cnsmr_accnt_pymnt_jrnl is a table with all transactions.
cnsmr_accnt_tag is a table with the tags assigned to accounts.
I am trying to determine which area tag was assigned to an account at the time of a payment.
The way that the cnsmr_accnt_tag table works is that when a tag is assigned to an account, the field cnsmr_accnt_tag_assgn_dt (datetime) gets updated as well as the field upsrt_dttm (datetime) and the field cnsmr_accnt_sft_delete_flg is set to N. At this point the cnsmr_accnt_tag_assgn_dt and upsrt_dttm fields have the same datetime.
When the tag is unassigned, the cnsmr_accnt_sft_delete_flg field is set to Y and the upsrt_dttm is updated to that datetime such that the difference between the 2 fields indicates how long the account spent with that tag assigned.
I want to be able to determine which tag_id with tag_typ_id = 60 (the area tag type) was assigned to that account when the payment happened.
The problem is that an account can move into one area, then out again and back in to the same area many times. It could today be in very different area to where it was when the payment was made or it could be in the same area. Essentially what I need to do is determine which area tag was assigned most recently (in the past) to the payment. Any suggestions?
TABLES:
Cnsmr_accnt_pymnt_jrnl
<table style="width:100%">
<tr>
<th>cnsmr_accnt_id</th>
<th>cnsmr_accnt_pymnt_amnt</th>
</tr>
<tr>
<td>562590</td>
<td>-565.090</td>
</tr>
<tr>
<td>562590</td>
<td>-565.090</td>
</tr>
<tr>
<td>562607</td>
<td>-27208.180</td>
</tr>
<tr>
<td>562618</td>
<td>200.000</td>
</tr>
</table>

I want to retrieve 'paid' value from and it is in 2nd row 2nd column using selenium

Below is the table code:
<table>
<tbody>
<tr>
<th>Automation Tool</th>
<th>Licensing</th>
<th>Market response</th>
</tr>
<tr>
<td>Selenium</td>
<td>Free</td>
<td>In</td>
</tr>
<tr>
<td>QTP</td>
<td>Paid</td>
<td>Out</td>
</tr>
</tbody>
</table>
driver.findElement(By.xpath("//table[#id='yourTableid']/tr[3]/td[2]")).getText();
Above code will fetch value from 2nd column of 2nd row of your table. You just need to know the table id. If you don't have table id, you need to find other table attribute to find the table first.
Edited to correct row. Thanks Sudharsan.

Group attribute in Coldfusion not working right

I'm trying to display options for homes and the categories in which they're in. Formatted in this way:
Category 1 Category 2
---------- ----------
option 1 Option 2
I have gotten very close. The options are showing up as expected, but the categories are repeating themselves. I've included an image.
I've tried all combinations of group in the CFOUTPUT and in the SQL with no success. I would appreciate some ideas. This is my current code:
<cfquery datasource="applewood" name="categorize">
SELECT idOptions
, options.option
, options.idOpCategories
, op_categories.categoryName
FROM options, op_categories
GROUP BY idOptions
</cfquery>
...
<cfoutput query="categorize" group="idOpCategories">
<h3>#UCASE(categoryName)#</h3>
<ul>
<cfoutput>
<li>#option#</li>
</cfoutput>
</ul>
</cfoutput>
Update:
I ordered and grouped by the same column and getting this result:
You are missing a JOIN clause between the "options" and "op_categories" tables, so the result is an implicit CROSS JOIN or cartesian product:
... it will produce rows which combine each row from the
first table with each row from the second table
Hence the duplicates. You need to join the two tables on the related column ie the category id.
Also, as Scott mentioned in the comments, cfoutput group only works with sorted query results. However, the results must be sorted by the same columns - in the same order - as your grouping. Otherwise, it can create the appearance of duplicated categories. So if you are grouping by "CategoryName" first, you should order by "CategoryName" first.
SELECT cat.categoryName, o.option, ...
FROM options o
INNER JOIN op_categories cat
ON cat.idOpCategories = o.idOpCategories
ORDER BY cat.categoryName, o.option
<cfoutput query="..." group="categoryName">
... more code ...
</cfoutput>
(In this specific case, you could technically use the category id as well)

Filtering a Measure (or Removing Outliers)

Say I have a measure, foo, in a cube, and I have a reporting requirement that users want to see the following measures in a report:
total foo
total foo excluding instances where foo > 10
total foo excluding instances where foo > 30
What is the best way to handle this?
In the past, I have added Named Calculations which return NULL if foo > 10 or just foo otherwise.
I feel like there has to be a way to accomplish this in MDX (something like Filter([Measures].[foo], [Measures].[foo] > 10)), but I can't for the life of me figure anything out.
Any ideas?
The trick is that you need to apply the filter on your set, not on your measure.
For example, using the usual Microsoft 'warehouse and sales' demo cube, the following MDX will display the sales for all the stores where sales were greater than $2000.
SELECT Filter([Store].[Stores].[Store].members, [Unit Sales] > 2000) ON COLUMNS,
[Unit Sales] ON ROWS
FROM [Warehouse and Sales]
I met similar problem when use saiku (backend with Mondrain), as I haven't found any clear solution of "add filter on measure", I added it here, and that may be useful for other guy.
In Saiku3.8, you could add filter on UI: "column"->"filter"->"custom", then you may see a Filter MDX Expression.
Let's suppose we want clicks in Ad greater than 1000, then add the following line there:
[Measures].[clicks] > 1000
Save and close, then that filter will be valid for find elem with clicks greater than 1000.
The MDX likes below (suppose dt as dimension and clicks as measure, we want to find dt with clicks more than 1000)
WITH
SET [~ROWS] AS
Filter({[Dt].[dt].[dt].Members}, ([Measures].[clicks] > 1000))
SELECT
NON EMPTY {[Measures].[clicks]} ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [OfflineData]
i think you have two choices:
1- Add column to your fact(or view on data source view that is based on fact table)like:
case when unit_Price>2000 then 1
else 0
end as Unit_Price_Uper_Or_Under_10
and add a fictitious Dimension based on this columns value.
and add named query for New Dimension(say Range_Dimension in datasourceview :
select 1 as range
union all
select 0 as range
and after taht you cant used this filter like other dimension and attribute.
SELECT [Store].[Stores].[Store].members ON COLUMNS,
[Unit Sales] ON ROWS
FROM [Warehouse and Sales]
WHERE [Test_Dimension].[Range].&[1]
the problem is for every range you must add When condition and only if the range is static this solution is a good solution.
and for dynamic range it's better to formulate the range (based on disceretizing method )
2- add dimension with granularity near fact table based on fact table
for example if we have fact table with primary key Sale_id.we can add
dimension based on fact table with only one column sale_Id and in dimension Usage tab
we can relate this new dimension and measure group with relation type Fact and
after that in mdx we can use something like :
filter([dim Sale].[Sale Id].[Sale Id].members,[Measures].[Unit Price]>2000)