-I use SSAS 2012 SP4 tabular version.
The cube contains 2 facts tables and each one uses the same dimension tables (=7 dimension tables).
There is no relation defined between 2 fact tables.
-The following measure is setup in Fact2 table:
Measure1 :=
IF (
SUM ( Fact1[ColumnA] ) = 0,
BLANK (),
IF (
SUM ( Fact2[ColumnB] ) > 0,
SUM ( Fact1[ColumnA] ) / SUM ( Fact2[ColumnB] ),
99
)
)
My Excel report is very long to refresh when I display this measure and several attributes.
-When I active a profiler trace I can see that the time spend in the Formula Engine is 80%.
I have tried to rewrite the query with using the function DIVIDE() like this :
Measure1 := DIVIDE(sum(Fact1[ColumnA])/sum(Fact2[ColumnB]),99)
In this case the report is fast and query duration is better. But as I have removed the IF function I don't check any more "if sum(Fact1[ColumnA])=0"
It is possible to refactor this DAX formula in order to improve performance. And keeping the check "IF sum(Fact1[ColumnA])=0 THEN BLANK()" ?
Thanks a lot for your help
Em
Sure, try this:
Measure 1 :=
VAR SUMA =
SUM ( 'Fact1'[ColumnA] )
VAR SUMB =
SUM ( 'Fact2'[ColumnB] )
VAR QUOT =
DIVIDE ( SUM ( 'Fact1'[ColumnA] ), SUM ( 'Fact2'[ColumnB] ) )
RETURN
SWITCH ( TRUE (), SUMA = 0, BLANK (), SUMB > 0, QUOT, 99 )
If you can't use Variables in your measures, try this:
Measure1 :=
SWITCH (
TRUE (),
SUM ( 'Fact1'[ColumnA] ) = 0, BLANK (),
SUM ( 'Fact2'[ColumnB] ) > 0, DIVIDE ( SUM ( 'Fact1'[ColumnA] ), SUM ( 'Fact2'[ColumnB] ) ),
99
)
Another method would be to create a calculated column like so:
result := DIVIDE ( SUM ( 'Fact1'[ColumnA] ), SUM ( 'Fact2'[ColumnB] )
)
Then, write a measure against it like this:
Measure1 :=
SWITCH ( TRUE (), [result] = 0, BLANK (), [result] > 0, [result], 99 )
I haven't tested either of these so I am not sure how their performance will be.
Hope it helps!
Related
I am trying to create KPI and for that i try to create a variable
i have this formula
Total_Sales_Variable =
IF (
VALUES (BillingDocument_Header[Billing Doc. currency_WAK] ) = "USD",
139.2,
1
) *
CALCULATE (
SUM (BillingDocument_Item[Sales Amount_NEWR]),
FILTER (
'Invoice_Calender',
'Invoice_Calender'[Fiscal_Year] = 2016 &&
'Invoice_Calender'[Fiscal_Year] = 2017
),
FILTER (
'BillingDocument_Header',
'BillingDocument_Header'[Bill Type_FKRT] <> "Z2" &&
'BillingDocument_Header'[Bill Type_FKRT] <> "Z2"
)
)
when i add this shows an error
MdxScript(Model) (8, 5) Calculation error in measure 'Invoice_Calender'[Total_Sales_Variable]: A table of multiple values was supplied where a single value was expected.
and i am trying of achieve if Billing Doc. currency_WAk is USD then i want to sum of this field Sales Amount_NEWR against filters Fiscal_Year = {'2016','2017'} and [Billing Type_FKART] ={'ZG2','ZL2'}
this is what i want to achieve in power bi i want to convert this into dax expression power bi
qlik sense expression
if([Billing Doc. currency_WAERK] = 'USD',
sum({< Fiscal_Year = {'2016','2017'},[Billing Type_FKART] -={'ZG2','ZL2'}>}[Billing Sales Amount_NETWR])*139.2,
sum({< Fiscal_Year = {'2016','2017'},[Billing Type_FKART] -={'ZG2','ZL2'}>}[Billing Sales Amount_NETWR]))
any help ?
UPDATE ATTACHED FILE
kindly check pbix file with data and tables
https://www.dropbox.com/s/flondhallo08j98/test4.pbix?dl=0
Edited: Now we finally have clarity on your table structure and relationships, and understand your required measure!
Total Sales Variable =
CALCULATE (
SUMX (
VALUES ( test_billing_doc_header[Billing Doc. currency_WAERK] ),
IF (
test_billing_doc_header[Billing Doc. currency_WAERK] = "USD",
139.2,
1
) * SUM ( test_biilingg_doc_item[Billing Sales Amount_NETWR] )
),
Invoice_Calender[Fiscal_Year] = 2016 || Invoice_Calender[Fiscal_Year] = 2017,
test_billing_doc_header[Billing Type_FKART] <> "ZG2" && test_billing_doc_header[Billing Type_FKART] <> "ZL2"
)
PBIX file: https://pwrbi.com/so_55914086-3/
I have a PostgreSQL table like this:
CREATE TABLE foo (man_id, subgroup, power, grp)
AS VALUES
( 1, 'Sub_A', 1, 'Group_A' ),
( 2, 'Sub_B', -1, 'Group_A' ),
( 3, 'Sub_A', -1, 'Group_B' ),
( 4, 'Sub_B', 1, 'Group_B' ),
( 5, 'Sub_A', -1, 'Group_A' ),
( 6, 'Sub_B', 1, 'Group_A' ),
( 7, 'Sub_A', -1, 'Group_B' ),
( 8, 'Sub_B', 1, 'Group_B' );
The power calculation works like this:
Total Power of Subgroup Sub_A in the grp Group_A is (1 + (-1) ) = 0
Total Power of Subgroup Sub_B in the grp Group_A is ((-1) + 1 ) = 0
Total Power of Subgroup Sub_A in the grp Group_B is ((-1) + (-1) ) = -2
Total Power of Subgroup Sub_B in the grp Group_B is (1 + 1 ) = 2
So the power of Sub_A in the Group_A is not equal to power of Sub_A in the Group_B
So the power of Sub_B in the Group_A is not equal to power of Sub_B in the Group_B
I want to query the database with a subgroup name. If for a same subgroup name power is equal across all the other grp names, then it will return True, else False.
As an example, sub_A and sub_B both will return False. What would be the recommended way to do this?
I want something like:
SELECT * FROM foo (solution query will be added)
WHERE subgroup = 'sub_A'
And it returns False.
Read the question carefully
I want to query the database with a subgroup name.
And:
I want something like
SELECT * FROM foo (solution query will be added)
WHERE subgroup = 'Sub_A'
The important point for performance is to exclude irrelevant rows early and only compute aggregates for the given subgroup. Then (assuming more than a few distinct subgroups), an index on (subgroup) can help:
CREATE INDEX ON foo (subgroup);
Each of the following queries returns FALSE if at least two groups have different total sums for the given subgroup, and TRUE in all other cases (with a minor exception for query 5, see below).
Query 1
SELECT count(DISTINCT total_power) = 1
FROM (
SELECT sum(power) AS total_power
FROM foo
WHERE subgroup = 'Sub_B' -- exclude irrelevant rows early!
GROUP BY grp
) sub;
Query 2
SELECT count(*) = 1
FROM (
SELECT true
FROM (
SELECT sum(power) AS total_power
FROM foo
WHERE subgroup = 'Sub_C'
GROUP BY grp
) sub2
GROUP BY total_power
) sub2;
Query 3
SELECT count(*) OVER () = 1
FROM (
SELECT sum(power) AS total_power
FROM foo
WHERE subgroup = 'Sub_A'
GROUP BY grp
) sub
GROUP BY total_power
LIMIT 1;
Query 4
(
SELECT FALSE
FROM (
SELECT sum(power) AS total_power
FROM foo
WHERE subgroup = 'Sub_A'
GROUP BY grp
) sub
GROUP BY total_power
OFFSET 1
LIMIT 1
)
UNION ALL
SELECT TRUE
LIMIT 1;
This one is special. Related answers with explanation:
Return a value if no record is found
Way to try multiple SELECTs till a result is available?
Query 5
SELECT min(total_power) = max(total_power) -- can fail for NULL values
FROM (
SELECT sum(power) AS total_power
FROM foo
WHERE subgroup = 'Sub_A'
GROUP BY grp
) sub;
The last can fail if NULL values in power are allowed. (But you would have to define expected results in this case anyway.)
I ran an extensive test and found all queries to perform about the same under ideal conditions:
db<>fiddle here
Query 5 tended to be a tad bit faster than the rest.
Assuming that in your CREATE TABLE statement, 'sub_A' is meant to be 'Sub_A' (because Postgres is case-sensitive), and that your power values are actually integers (if they aren't, just add casts; the code below is simpler without them), then you can calculate the power for each subgroup within a group as follows:
select
subgroup,
grp,
sum(power) as sum_power
from
foo
group by
subgroup,
grp
To determine whether all of the total power values for a subgroup are the same, just check that the minimum and maximum values are the same. Convert the previous query into a subquery, where the main query does that comparison, as follows:
select
subgroup
from (
select
subgroup,
grp,
sum(power) as sum_power
from
foo
group by
subgroup,
grp
) as subpwr
group by
subgroup
having
min(sum_power) = max(sum_power);
Here's 1 way not yet mentioned by the other answers
SELECT SUM(power) = FIRST_VALUE(SUM(power)) OVER () powpow
FROM foo
WHERE subgroup = 'Sub_A'
GROUP BY grp
ORDER BY powpow
LIMIT 1
-- returns:
-- false if some values differ
-- true if all values are the same
-- no rows if the where condition fails to match any rows.
Here's a simplified version of my model:
I have P/L (profit and loss) data at the daily level for several funds and several securities. To calculate the % return is easy - it's the P/L divided by the opening AUM (assets under management). But each month the AUM changes significantly due to investor contributions. So, to get a YTD return %, I need to calculate cumulative returns, for which the formula is (see here):
YtdReturn =
PRODUCTX ( MonthlyReturnTable, DIVIDE ( MonthlyReturn, OpeningAUM ) +1 ) -1
The difficulty is that my P/L is at the daily level. I successfully created this:
CompoundReturn:=
PRODUCTX (
ADDCOLUMNS (
VALUES ( tblDates[MonthYearNumber] ),
"PnL Total1", CALCULATE ( SUM ( PnL[TradingPnL] ) + SUM ( PnL[InterestDividendsPnL] ) ),
"Month_Opening_AUM1", CALCULATE ( VALUES ( Daily_AUM[MonthOpeningAUM] ) )
),
DIVIDE ( [PnL Total1], [Month_Opening_AUM1] ) + 1
)
- 1
This works well:
However, I want to do this on a running YTD basis. I'm having trouble setting the "inner" table to YTD. I tried surrounding the VALUES() with a CALCULATETABLE() to filter by YTD, but didn't work:
CompoundReturn :=
PRODUCTX (
ADDCOLUMNS (
CALCULATETABLE (
VALUES ( tblDates[MonthYearNumber] ),
DATESYTD ( tblDates[Date] )
),
"PnL Total1", CALCULATE ( SUM ( PnL[TradingPnL] ) + SUM ( PnL[InterestDividendsPnL] ) ),
"Month_Opening_AUM1", CALCULATE ( VALUES ( Daily_AUM[MonthOpeningAUM] ) )
),
DIVIDE ( [PnL Total1], [Month_Opening_AUM1] ) + 1
)
- 1
The result in Excel is not a running return, but individual:
Any ideas? Thanks!
Note: All code formatted with daxformatter.com
Figured it out with the help of a friend. I needed to put the CALCULATETABLE outside the ADDCOLUMNS:
CompoundReturn :=
PRODUCTX (
CALCULATETABLE (
ADDCOLUMNS (
VALUES ( tblDates[MonthYearNumber] ),
"PnL Total1", CALCULATE ( SUM ( PnL[TradingPnL] ) + SUM ( PnL[InterestDividendsPnL] ) ),
"Month_Opening_AUM1", CALCULATE ( VALUES ( Daily_AUM[MonthOpeningAUM] ) )
),
DATESYTD ( tblDates[Date] )
),
DIVIDE ( [PnL Total1], [Month_Opening_AUM1] ) + 1
)
- 1
I'm using the RAND function in bigquery to provide me with a random sample of data, and unioning it with another sample of the same dataset.
This is for a machine learning problem where I'm interested in one class more than the other.
I've recreated the logic using a public dataset.
SELECT
COUNT(1),
bigarticle
FROM
(
SELECT
1 as [bigarticle]
FROM [bigquery-public-data:samples.wikipedia]
WHERE num_characters > 50000
),
(
SELECT
0 as [bigarticle]
FROM [bigquery-public-data:samples.wikipedia]
WHERE (is_redirect is null) AND (RAND() < 0.01)
)
GROUP BY bigarticle
Most of the time this behaves as expected,
giving one row with the count of rows where num_characters is more than 50k,
and giving another row with a count of a 1% sample of rows where is_redirect is null.
(This is an approximation of the logic I use in my internal dataset).
If you run this query repeatedly, occasionally it gives unexpected results.
In this result set (bquijob_124ad56f_15da8af982e) I only get a single row, containing the count of bigarticle = 1.
RAND does not use a deterministic seed. If you want deterministic results, you need to hash/fingerprint a column in the table and use a modulus to select a subset of values instead. Using legacy SQL:
#legacySQL
SELECT
COUNT(1),
bigarticle
FROM (
SELECT
1 as [bigarticle]
FROM [bigquery-public-data:samples.wikipedia]
WHERE num_characters > 50000
), (
SELECT
0 as [bigarticle]
FROM [bigquery-public-data:samples.wikipedia]
WHERE (is_redirect is null) AND HASH(title) % 100 = 0
)
GROUP BY bigarticle;
Using standard SQL in BigQuery, which is recommended since legacy SQL is not under active development:
#standardSQL
SELECT
COUNT(*),
bigarticle
FROM (
SELECT
1 as bigarticle
FROM `bigquery-public-data.samples.wikipedia`
WHERE num_characters > 50000
UNION ALL
SELECT
0 as bigarticle
FROM `bigquery-public-data.samples.wikipedia`
WHERE (is_redirect is null) AND MOD(FARM_FINGERPRINT(title), 100) = 0
)
GROUP BY bigarticle;
I'm looking for a elegant MDX expression that sum values only of the elements of last level dimension:
I have a measure M , also I have a hierarchical parent - child dimension U that is non balanced tree:
R -> ( M = R1 + R2 = 157 )
..R1 -> ( M = R11 + R12 = 150 )
...R11 -> ( M=R111 = 100 )
.....R111 -> M=100
...R12 -> M = 50
..R2 -> M = 7
I have a set that contains some elements from this dimension:
S contains R11, R111, R12
Now I need to take, for a U.currentMember the M value (that is, the sum of last level descendants)
I have written this expression, it works but perhaps they are a more elegant way to write it:
with member measures.XX as
sum (
intersect(
[S],
Except(
descendants( [U].currentMember ),
existing( descendants( [U].currentMember ).item(0) )
)
)
,
[M]
)
select
measures.xx on columns
from [CUBE]
where [U].[R]
Note: This MDX dont run:
with member measures.XX as
sum (
intersect(
[S],
descendants( [U].currentMember )
)
,
[M]
)
select
measures.xx on columns
from [CUBE]
where [U].[R]
because return 250 insteat 150.
Right result is 150: R11 + R12 (because R111 is included in R11).
Bad result is: 250: '100' value is taked for twice R11 + R111.
Final Solution:
with member measures.XX as
sum(
intersect (
descendants([U].currentMember,,leaves),
[S]
)
,
[M]
)
select
measures.XX on 0,
descendants( [Unitats].[Unitat].[All] ) on 1
from [C]
Not sure what you want to calculate but let's assume [Member] is the member you want to evaluate :
I'd use the descendants, filter and isLeaf MDX functions :
Sum(
Filter( Descendants( [Member] ), isLeaf(Member_hierarchy.currentmember) )
,[M])
You're adding all descendants including itself that are leafs (no children).