DAX SUMX over 2 levels - powerpivot

This should be easy but I must be missing something obvious. I have the following PowerPivot table:
Level 1 Level 2 Amount
------- ------- ------
A X 100
A Y 200
B X 400
B Y 600
I'm trying to build a measure (not a calculated column) that iterates over each item in Level 2 and divides the amount by the subtotal of all amounts for Level 1 equal to the current Level 1 amount.
In other words, I want the measure to do this
Level 1 Level 2 Measure
------- ------- ------
A X 100 / 300
A Y 200 / 300
B X 400 / 1,000
B Y 600 / 1,000
I have tried this:
AmountSum:=SUM(Table1[Amount])
Measure:= SUMX(Table1,
[AmountSum]/CALCULATE(SUMX(Table1, [AmountSum]), ALL(Table1[Level 2])))
This and other iterations I've tried always end up showing 1 for each calc meaning that (or so it appears) only the initial Level 2 row is in scope when calc'ing the denominator, despite my use of ALL.
Thanks in advance for any advice people can offer!
Edit:
Assume that the [AmountSum] logic is dependent on and needs to be calculated at the row level for the Level 2 items. It was simplified in the example above, but in reality it is dependent on the Level 2 data and at a Level 1 level should only be adding up results calculated at a Level 2 level.

Try this:
AmountSum:=SUM(Table1[Amount])
Measure:= DIVIDE([AmountSum], CALCULATE([AmountSum], ALL(Table1[Level 2])))
If it has to be calculated at the leaf level:
AmountSum:=SUMX(Table1, <YourMoreComplexCalcHere>)
Measure:= DIVIDE([AmountSum], CALCULATE([AmountSum], ALL(Table1[Level 2])))

Related

How to write a basic SQL function to match values with a maximum and minimum range of values?

If I have a data set like the following :
type| min | max
-----------------
a | 25 | 30
b | 20 | 30
c | 15 | 20
My goal is to match an input with a type, and to do that while taking into account that my types have overlapping values.
So let's say I have an input in my system that is 25, and I want to match my input to a type (either a, b, or c). My input is most likely b, since the average of the min and max of b is 25, and could possibly be a, but that is less likely. I've tried implementing this and have had no luck, and have also thought of using p-values, but am not sure how I can do it.
What would be the best way to implement this?
Something like this fits your description:
select t.*
from t
where ? >= min and ? <= max
order by abs( ? - (max - min) / 2 )
fetch first 1 row only;
This identifies the ranges where the value matches. It then chooses the range where the value is closest to the middle of the range.

Calculate percentage between two values

I have two columns that hold numbers for which I am trying to calculate the difference in % between and show the result in another column but the results seem to be wrong.
This is the code in question.
SELECT
GenPar.ParameterValue AS ClaimType,
COUNT(Submitted.ClaimNumber) AS SubmittedClaims,
COUNT(ApprovalProvision.ClaimNumber) AS ApprovedClaims,
COUNT(Declined.ClaimNumber) AS DeclinedClaims,
COUNT(Pending.ClaimNumber) AS PendingClaims,
ISNULL(SUM(SubmittedSum.SumInsured),0) AS TotalSubmittedSumInsured,
ISNULL(SUM(ApprovedSum.SumInsured),0) AS TotalApprovedSumInsured,
ISNULL(SUM(RejectedSum.SumInsured),0) AS TotalRejectedSumInsured,
ISNULL(SUM(PendingSum.SumInsured),0) AS TotalPendingSumInsured,
--This column is to show the diff in %
CASE WHEN COUNT(Submitted.ClaimNumber) <> 0 AND COUNT(ApprovalProvision.ClaimNumber) <> 0
THEN (COUNT(ApprovalProvision.ClaimNumber),0) - (COUNT(Submitted.ClaimNumber),0)
/COUNT(Submitted.ClaimNumber) * 100
ELSE 0
END
What I need is to show the difference in % between the columns SubmittedClaims and ApprovedClaims. Any column, or both may contain zeroes and it may not.
So it's: COUNT(Submitted.ClaimNumber) - COUNT(ApprovalProvision.ClaimNumber) / COUNT(Submitted.ClaimNumber) * 100 as far as I know.
I have tried this and an example of what it does is it takes 1 and 117 and returns 17 when the difference between 1 and 117 is a decrease of 99.15%. Another example is 2 and 100. This simply returns 0 whereas the difference is a decrease of 98%.
CASE WHEN COUNT(Submitted.ClaimNumber) <> 0 AND COUNT(ApprovalProvision.ClaimNumber) <> 0
THEN (COUNT(ApprovalProvision.ClaimNumber),0) - (COUNT(Submitted.ClaimNumber),0)
/COUNT(Submitted.ClaimNumber) * 100
ELSE 0
END
I've checked this link and this seems to be what I am doing.
Percentage difference between two values
I've also tried this code:
NULLIF(COUNT(Submitted.ClaimNumber),0) - NULLIF(COUNT(ApprovalProvision.ClaimNumber),0)
/ NULLIF(COUNT(Submitted.ClaimNumber),0) * 100
and this takes for example 2 and 100 and returns -4998 when the real difference is a decrease of 98%.
For completion, Submitted.ClaimNumber is this portion of code:
LEFT OUTER JOIN (SELECT * FROM Company.Schema.ClaimMain WHERE CurrentStatus=10)Submitted
ON Submitted.ClaimNumber = ClaimMain.ClaimNumber
ApprovalProvision.ClaimNumber is this:
LEFT OUTER JOIN (SELECT * FROM Company.Schema.ClaimMain WHERE CurrentStatus=15)ApprovalProvision
ON ApprovalProvision.ClaimNumber = ClaimMain.ClaimNumber
Ideally, this column would also deal with 0's. So if one value is 0 and the other is X, the result should return 0 since a percentage can't be calculated if original number is 0. If the original value is X and the new value is 0, I should show a decrease of 100%.
This will occur across all columns but there is no need to flood the page with the rest of the columns since all calculations will occur in the same manner.
Anybody see what I'm doing wrong?
I'm not familiar with why you have (x,0) as a syntax
But I see that you have
(COUNT(ApprovalProvision.ClaimNumber),0) - (COUNT(Submitted.ClaimNumber),0)
/COUNT(Submitted.ClaimNumber) * 100
shouldn't it be,
( COUNT(ApprovalProvision.ClaimNumber) - COUNT(Submitted.ClaimNumber) )
/COUNT(Submitted.ClaimNumber) * 100
It looks like it would do count of ApprovalProvision.ClaimNumber - 100 since submitted.claimnumber divided by itself is 1 times 100 is 100.
The 4900 number actually sounds right. Lets take the following example, you have 2 apples, and then you're given 98 more and got 100 apples.
An increase of 98% would have meant from 2 apples, you would have 3.96 apples.
An increase of 100% means from 2 apples you end with 4 apples. An increase of 1000% means from 2 apples you end with 22 apples. So 4000% means you end with 82 apples. 5000% means from 2 apples, you reach 102 apples.
(100-2)/2*100 = 98 / 2 = 49 * 100 = 4900, so it looks like there is a 4900% increase in number of apples if you started with 2 apples and reach 100.
Now if you had flipped the 2 and 100, say starting with 100, now you have 2,
(2-100)/100*100 = -98, so a -98% change of apples, or a 98% decrease.
Hope this solves your problem.

MDX Aggregate DImensions to filter

I'm new to mdx and need your help:
[Item].[Segment] [Country].[World] [Measures].[Periodic]
1 Region A 150
2 Region B 60
3 Region C 1400
4 Region D 20
I have two dimensions Segment and World. If I take only world, I get no values. But I want to achieve to combine the two dimensions to one dimension on segment level as following:
[Item].[Segment] [Measures].[Periodic]
1 150
2 60
3 1400
4 20
Would an aggregation be useful in this case?
Thanks in advance!
The Structure is like following:
Cube_Structure
--> I need to combine both dimensions Segment and World in order to have one dimension on the row which shows me the values for the segments only!

Select minimum value from column A where column B is not in an array

I'm trying to select accesses for patients where d11.xblood is a minimum value grouped by d11.xpid - and where d11.xcaccess_type is not 288, 289, or 292. (d11.xblood is a chronological index of accesses.)
d11.xpid: Patient ID (int)
d11.xblood: Unique chronological index of patients' accesses (int)
d11.xcaccess_type: Unique identifier for accesses (int)
I want to report one row for each d11.xpid where d11.xblood is the minimum (initial access) for its respective d11.xpid . Moreover, I want to exclude the row if the initial access for a d11.xpid has a d11.xcaccess_type value of 288, 289 or 292.
I have tried several variations of this in the Select Expert:
{d11.xblood} = Minimum({d11.xblood},{d11.xpid}) and
not ({d11.xcaccess_type} in [288, 289, 292])
This correctly selects rows with the initial access but eliminates rows where the current access is not in the array. I only want to eliminate rows where the initial access is not in the array. How can I accomplish this?
Sample table:
xpid xblood xcaccess_type
---- ------ -------------
1 98 400
1 49 300
1 152 288
2 33 288
2 155 300
2 70 400
3 40 300
3 45 400
Sample desired output:
xpid xblood xcaccess_type
---- ------ -------------
1 49 300
3 40 300
See that xpid = 2 is not in the output because its minimum value of xblood had an xcaccess_type = 288 which is excluded. Also see that even though xpid = 1 has an xcaccess_type = 288, because there is a lower value of xblood for xpid = 1 where xcaccess_type not in (288,289,292) it is still included.
If you don't want to write a stored procedure or custom SQL to handle this, you could add another Group. Assuming your deepest group (the one closest to the Details section) is sorting based on xpid, you could add a group inside that one which sorts the xcaccess_type from lowest to highest.
Suppress the header and footer for the new group then add this clause to the details section:
({d11.xpid} = PREVIOUS({d11.xpid})
OR
({d11.xcaccess_type} in [288, 289, 292])
This should modify your report to only ever display the records with the lowest access value per person. And if the lowest access value is one of the three forbidden values, no records will show for that xpid.

sql more complicated querying measurements

I have two tables (sql server), as shown below:
locations
id cubicfeet order
-------------------------------------
1 5 1
2 10 1
3 6 1
items
id cubic feet order
--------------------------------------
1 6 1
2 6 1
3 6 1
I need a query to tell me if all the items will fit into all the locations (for a given order). If all items will not fit into 1 or all locations then I need to create a new location for that given order - and then move any items that DID fit into the locations before to the new location (as many as fit). The new location will only be given a certain amount of cubic feet also - say 17. In this example, sum won't work because all 3 records are 6 so the sum is 18, which is less than the sum of 5,10,6, but the location with volume 5 can't fit any of the items since they are all volume 6 cubic feet.
the only way I think I can do it is creating temp tables in my sp and using a while loop to go through them and update the locations 1 at a time to see if it still fits more...