MDX: Query if row exists in dimension - mdx

I have created a SSAS Tabular model cube which this connects too.
The cube contains
Measures: - CountA, SumB, CountC, SumD, CountE
Dimensions:
- TblLabelDefinition(ID,Definition,Type)
- TblLabels(ID,Type,reference,date,sold,leftover,A,B,C,D,E)
- References(ID,reference,date)
Below is a query I am working on:
SELECT
NON EMPTY
{
[Measures].[CountA],
[Measures].[SumB],
[Measures].[CountC],
[Measures].[SumD],
[Measures].[CountE]
}
ON COLUMNS,
NON EMPTY
{
(
[TblLabelDefinition].[Definition].[Definition].ALLMEMBERS *
[TblLabels].[Type].[Type].ALLMEMBERS
)
}
DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM
(
SELECT ( -{ [TblLabels].[sold].&[1] } ) ON COLUMNS
FROM
( SELECT ( { [TblLabels].[leftover].&[0] } ) ON COLUMNS
FROM [Model]
)
)
WHERE
( [TblLabels].[leftover].&[0] )
AND
(
EXISTS([TblLabels].[reference], [References].[reference])
)
CELL PROPERTIES VALUE, BACK_COLOR, FORE_COLOR,
FORMATTED_VALUE, FORMAT_STRING, FONT_NAME, FONT_SIZE, FONT_FLAGS
I am trying to check if reference in the TblLabels table exists in References table.
This is the error I get:
The And function expects a string or numeric expression for the 2 argument. A tuple set expression was used.

Try the below to get rid of the syntactic error:
SELECT
NON EMPTY
{
[Measures].[CountA],
[Measures].[SumB],
[Measures].[CountC],
[Measures].[SumD],
[Measures].[CountE]
}
ON COLUMNS,
NON EMPTY
{
(
[TblLabelDefinition].[Definition].[Definition].ALLMEMBERS *
[TblLabels].[Type].[Type].ALLMEMBERS
)
}
DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM
(
SELECT ( -{ [TblLabels].[sold].&[1] } ) ON COLUMNS
FROM
( SELECT ( { [TblLabels].[leftover].&[0] } ) ON COLUMNS
FROM [Model]
)
)
WHERE
(
[TblLabels].[leftover].&[0]
,
(
EXISTS
(
[TblLabels].[reference],
[References].[reference]
)
))
CELL PROPERTIES VALUE, BACK_COLOR, FORE_COLOR,
FORMATTED_VALUE, FORMAT_STRING, FONT_NAME, FONT_SIZE, FONT_FLAGS
As a side note:
EXISTS
(
[TblLabels].[reference],
[References].[reference]
)
yields a set of those references that exists in the table TblLabels for one or more references in the table References. If these tables are joined on the 'reference' column then the above EXISTS construct would return only those references that are present in both References and TblLabels. Do check if that is what you needed in the first place.

Related

Using OR condition in MDX with different hierarchies of same dimension

I would like to get data from cube where [Product].[Product Level2].&[S1050]&[S1050.080] OR [Product].[Product Level4].&[S1060.012.701003]. So combine two hierarchies from same measure in set.
SELECT NON EMPTY {
[Measures].[Product Sales], [Measures].[Sales Quantity]
} ON COLUMNS,
NON EMPTY { (
[Product].[EAN CODE].[EAN CODE].ALLMEMBERS
* [Product].[Product].[Product].ALLMEMBERS
* [Date].[Calender Week].[Calender Week].ALLMEMBERS
* [Store].[Store Code].[Store Code].ALLMEMBERS
* [Store].[Store].[Store].ALLMEMBERS
) } ON ROWS
FROM (
SELECT ( -{ [Store].[Store Code].&[0032], [Store].[Store Code].&[0033] } ) ON COLUMNS FROM (
SELECT ( { [Date].[Calender Week].&[2019]&[IW201906] } ) ON COLUMNS FROM [Cube]
)
)
WHERE (
{[Product].[Product Level2].&[S1050]&[S1050.080], [Product].[Product Level4 Code].&[S1060.012.701003]}
)
The above query is returning "Members, tuples or sets must use the same hierarchies in the function."
Thank you for helping
You need to write your where like this
{(
[Product].[Product Level2].&[S1050]&[S1050.080], [Product].[Product Level4 Code].defaultmember),
{[Product].[Product Level2].defaultmember, [Product].[Product Level4 Code].&[S1060.012.701003]}
)

why Snowflake changing the order of JSON values when converting into flatten list?

I have JSON objects stored in the table and I am trying to write a query to get the first element from that JSON.
Replication Script
create table staging.par.test_json (id int, val varchar(2000));
insert into staging.par.test_json values (1, '{"list":[{"element":"Plumber"},{"element":"Craft"},{"element":"Plumbing"},{"element":"Electrics"},{"element":"Electrical"},{"element":"Tradesperson"},{"element":"Home services"},{"element":"Housekeepings"},{"element":"Electrical Goods"}]}');
insert into staging.par.test_json values (2,'
{
"list": [
{
"element": "Wholesale jeweler"
},
{
"element": "Fashion"
},
{
"element": "Industry"
},
{
"element": "Jewelry store"
},
{
"element": "Business service"
},
{
"element": "Corporate office"
}
]
}');
with cte_get_cats AS
(
select id,
val as category_list
from staging.par.test_json
),
cats_parse AS
(
select id,
parse_json(category_list) as c
from cte_get_cats
),
distinct_cats as
(
select id,
INDEX,
UPPER(cast(value:element AS varchar)) As c
from
cats_parse,
LATERAL flatten(INPUT => c:"list")
order by 1,2
) ,
cat_array AS
(
SELECT
id,
array_agg(DISTINCT c) AS sds_categories
FROM
distinct_cats
GROUP BY 1
),
sds_cats AS
(
select id,
cast(sds_categories[0] AS varchar) as sds_primary_category
from cat_array
)
select * from sds_cats;
Values: Categories
{"list":[{"element":"Plumber"},{"element":"Craft"},{"element":"Plumbing"},{"element":"Electrics"},{"element":"Electrical"},{"element":"Tradesperson"},{"element":"Home services"},{"element":"Housekeepings"},{"element":"Electrical Goods"}]}
Flattening it to a list gives me
["Plumber","Craft","Plumbing","Electrics","Electrical","Tradesperson","Home services","Housekeepings","Electrical Goods"]
Issue:
The order of this is not always same. Snowflake seems to change the ordering sometimes snowflake changes the order as per the alphabet.
How can I make this static. I do not want the order to be changed.
The problem is the way you're using ARRAY_AGG:
array_agg(DISTINCT c) AS sds_categories
Specifying it like that gives Snowflake no guidelines on how the contents of array should be arranged. You should not assume that the arrays will be created in the same order as their input records - it might, but it's not guaranteed. So you probably want to do
array_agg(DISTINCT c) within group (order by index) AS sds_categories
But that won't work, as if you use DISTINCT c, the value of index for each c is unknown. Perhaps you don't need DISTINCT, then this will work
array_agg(c) within group (order by index) AS sds_categories
If you do need DISTINCT, you need to somehow associate an index with a distinct c value. One way is to use a MIN function on index in the input. Here's a full query
with cte_get_cats AS
(
select id,
val as category_list
from staging.par.test_json
),
cats_parse AS
(
select id,
parse_json(category_list) as c
from cte_get_cats
),
distinct_cats as
(
select id,
MIN(INDEX) AS index,
UPPER(cast(value:element AS varchar)) As c
from
cats_parse,
LATERAL flatten(INPUT => c:"list")
group by 1,3
) ,
cat_array AS
(
SELECT
id,
array_agg(c) within group (order by index) AS sds_categories
FROM
distinct_cats
GROUP BY 1
),
sds_cats AS
(
select id,
cast(sds_categories[0] AS varchar) as sds_primary_category
from cat_array
)
select * from cat_array;

Filtered Parameters MDX error

New to mdx and trying to filter one parameter. I have the following,
WITH MEMBER [Measures].[ParameterCaption] AS IIF(IsEmpty([Measures].[Charge Count]),null, [Payment].[Description].CurrentMember .MEMBER_CAPTION)
MEMBER [Measures].[ParameterValue] AS IIF(IsEmpty([Measures].[Charge Count]), null, [Payment].[Description].CurrentMember.UniqueName)
MEMBER [Measures].[ParameterLevel] AS IIF(IsEmpty([Measures].[Charge Count]), null, [Payment].[Description].CurrentMember .Level .Ordinal)
SELECT
{ [Measures].[ParameterCaption],
[Measures].[ParameterValue],
[Measures].[ParameterLevel] } ON COLUMNS
, NONEMPTY ([Primary].[Description].ALLMEMBERS, [Measures].[Charge Count]) ON ROWS
FROM (SELECT (STRTOSET(#Client, CONSTRAINED) ON COLUMNS
FROM [DACUBE]))
with an error on the second to last line with the 'ON'. This all seems correct except this error. Can someone tell me where I'm going wrong?
I think your braces are not quite correct - try the following:
WITH
MEMBER [Measures].[ParameterCaption] AS
IIF
(
IsEmpty([Measures].[Charge Count])
,null
,[Payment].[Description].CurrentMember.Member_Caption
)
MEMBER [Measures].[ParameterValue] AS
IIF
(
IsEmpty([Measures].[Charge Count])
,null
,[Payment].[Description].CurrentMember.UniqueName
)
MEMBER [Measures].[ParameterLevel] AS
IIF
(
IsEmpty([Measures].[Charge Count])
,null
,[Payment].[Description].CurrentMember.Level.Ordinal
)
SELECT
{
[Measures].[ParameterCaption]
,[Measures].[ParameterValue]
,[Measures].[ParameterLevel]
} ON COLUMNS
,NonEmpty
(
[Primary].[Description].ALLMEMBERS
,[Measures].[Charge Count]
) ON ROWS
FROM
(
SELECT
StrToSet
(#Client
,CONSTRAINED
) ON COLUMNS
FROM [DACUBE]
);

Return a constant table from Inline-valued table

Is it possible to return a constant table from an IVT? Now i'm using a regular table, and function is just returning data from this table with several additional operations.
So i want to return a table
Value
-----
0,265433
0,0629412
0,671626
I tried something like this:
ALTER FUNCTION [dbo].[GetEigenvector]
(
)
RETURNS TABLE
AS
RETURN
(
SELECT Value = (SELECT 0,265433 UNION ALL
SELECT 0,0629412 UNION ALL
SELECT 0,671626)
)
but it throws an error:
Only one expression can be specified in the select list when the
subquery is not introduced with EXISTS.
You are messing up the syntax for giving an alias to your column:
ALTER FUNCTION [dbo].[GetEigenvector]
(
)
RETURNS TABLE
AS
RETURN
(
SELECT 0.265433 AS Value
UNION ALL
SELECT 0.0629412
UNION ALL
SELECT 0.671626
)
Another syntax:
alter function [dbo].[GetEigenvector]()
returns table as return
select * from
( values (0.265433), (0.0629412), (0.671626) )
as Eigenvector( Value );

Measure lacking context

I am struggling to force the measure CountTopPromos to be contextual.
Currently it is calculating a count of all the tuples in TopX. Against the version of AdWrks that I am running this is 14.
How do I force a context, of the current year, onto the measure CountTopPromos
WITH
SET FullSet AS
NonEmpty
(
[Date].[Calendar].[Calendar Year].MEMBERS
*
[Promotion].[Promotion].MEMBERS
,[Measures].[Reseller Order Count]
)
SET TopX AS
Generate
(
[Date].[Calendar].[Calendar Year].MEMBERS
,TopPercent
(
[Date].[Calendar].CurrentMember
*
Extract
(
FullSet
,[Promotion].[Promotion]
)
,90
,[Measures].[Reseller Order Count]
)
)
MEMBER [Measures].[CountTopPromos] AS
Count(TopX) //<<<<<<<<<<<< CONTEXT LACKING HERE <<<<<<<
SELECT
NON EMPTY
{[Measures].[CountTopPromos]} ON 0
,{TopX} ON 1
FROM [Adventure Works];
Currently it returns the following:
I'd like CountTopPromos to be in the context of the year so the desired output is as follows:
As sets are evaluated before the axes are defined (see my answer to this question), you cannot get row context into the calculation if you use the named set TopX. You could, however, copy its definition into the definition of [Measures].[CountTopPromos], replacing [Date].[Calendar].[Calendar Year].MEMBERS with [Date].[Calendar].CurrentMember:
MEMBER [Measures].[CountTopPromos] AS
Count(
Generate
(
[Date].[Calendar].currentMember
,TopPercent
(
[Date].[Calendar].CurrentMember
*
Extract
(
FullSet
,[Promotion].[Promotion]
)
,90
,[Measures].[Reseller Order Count]
)
)
)
delivers the result you want. And - as the Generate would loop over just one member here - you could omit that as well:
MEMBER [Measures].[CountTopPromos] AS
Count(
TopPercent
(
[Date].[Calendar].CurrentMember
*
Extract
(
FullSet
,[Promotion].[Promotion]
)
,90
,[Measures].[Reseller Order Count]
)
)
and will get the same result.
Another alternative that is quite pretty:
MEMBER [Measures].[CountTopPromos] AS
Count
(
Intersect
(
{
[Date].[Calendar].CurrentMember * [Promotion].[Promotion].MEMBERS
}
,TopX
)
)