QDR expressions in OLAP cube calculated measures - oracle

I'm becoming crazy with a calculated measure into OLAP Analytic Workspace Manager, that is defined like next OLAP Expression syntax:
NVL(CUBE.MEASURE1[DIM1= 'A'], 0) + NVL(CUBE.MEASURE2[DIM2= 'B'], 0)
Where:
CUBE.MEASURE1 and CUBE.MEASURE2 are not calculated measures, they are stored measures.
DIM1 and DIM2 are edges of the CUBE, A and B values both exist in their dimensions.
In most of all my queries, the calculated measure retrieves correct results, when both members of the sum retrieves data. But I other cases the calculated measure retrieves null !!!
In these cases, the calculated measure retrieves null when CUBE.MEASURE2[DIM2= 'B'] retrieves NO results. But I expect that if any of both QDR expresions retrieves no results, NVL function will replace it by 0.
I was reading about it, situations when QDR expressions retrieves no results, by default it throws and error and not null o NA value. I found that exist 2 ORACLE DML options that can manage this type of situations:
LIMITSTRICT = NO
(http://docs.oracle.com/cd/B28359_01/olap.111/b28126/dml_options043.htm#OLADM384)
OKNULLSTATUS = YES
(http://docs.oracle.com/cd/B28359_01/olap.111/b28126/dml_options077.htm#OLADM418)
I tried to create a DML Function in the AW to set both options, first to NO and second to YES, calling this function with OLAP_DML_EXPRESSION('MyFUNCTION', NUMBER) statement, but it doesn`t work
Please, I need a workaround of that, how I can catch these situations? Must I create a DML program to solve it? Where can I set this options (LIMITSTRICT,OKNULLSTATUS) by default and not set them in each measure calculation?

Related

Power BI DAX measure: Count occurences of a value in a column considering the filter context of the visual

I want to count the occurrences of values in a column. In my case the value I want to count is TRUE().
Lets say my table is called Table and has two columns:
boolean value
TRUE() A
FALSE() B
TRUE() A
TRUE() B
All solutions I found so far are like this:
count_true = COUNTROWS(FILTER(Table, Table[boolean] = TRUE()))
The problem is that I still want the visual (card), that displays the measure, to consider the filters (coming from the slicers) to reduce the table. So if I have a slicer that is set to value = A, the card with the count_true measure should show 2 and not 3.
As far as I understand the FILTER function always overwrites the visuals filter context.
To further explain my intent: At an earlier point the TRUE/FALSE column had the values 1/0 and I could achieve my goal by just using the SUM function that does not specify a filter context and just acts within the visuals filter context.
I think the DAX you gave should work as long as it's a measure, not a calculated column. (Calculated columns cannot read filter context from the report.)
When evaluating the measure,
count_true = COUNTROWS ( FILTER ( Table, Table[boolean] = TRUE() ) )
the first argument inside FILTER is not necessarily the full table but that table already filtered by the local filter context (including report/page/visual filters along with slicer selections and local context from e.g. rows/column a matrix visual).
So if you select Value = "A" via slicer, then the table in FILTER is already filtered to only include "A" values.
I do not know for sure if this will fix your problem but it is more efficient dax in my opinion:
count_true = CALCULATE(COUNTROWS(Table), Table[boolean])
If you still have the issue after changing your measure to use this format, you may have an underlying issue with the model. There is also the function KEEPFILTERS that may apply here but I think using KEEPFILTERS is overcomplicating your case.

Strange behaviour when using FILTER to filter a different table with no direct relationship?

I have two facts tables, First and Second, and two dimension tables, dimTime and dimColour.
Fact table First looks like this:
and facet table Second looks like this:
Both dim-tables have 1:* relationships to both fact tables and the filtering is one-directional (from dim to fact), like this:
dimColour[Color] 1 -> * First[Colour]
dimColour[Color] 1 -> * Second[Colour]
dimTime[Time] 1 -> * First[Time]
dimTime[Time] 1 -> * Second[Time_]
Adding the following measure, I would expect the FILTER-functuion not to have any affect on the calculation, since Second does not filter First, right?
Test_Alone =
CALCULATE (
SUM ( First[Amount] );
First[Alone] = "Y";
FILTER(
'Second';
'Second'[Colour]="Red"
)
)
So this should evaluate to 7, since only two rows in First have [Alone] = "Y" with values 1 and 6 and that there is no direct relationship between First and Second. However, this evaluates to 6. If I remove the FILTER-function argument in the calculate, it evaluates to 7.
There are thre additional measures in the pbix-file attached which show the same type of behaviour.
How is filtering one fact table which has no direct relationship to a second fact table affecting the calculation done on the second table?
Ziped Power BI-file: PowerBIFileDownload
Evaluating the table reference 'Second' produces a table that includes the columns in both the Second table, as well as those in all the (transitive) parents of the Second table.
In this case, this is a table with all of the columns in dimColour, dimTime, Second.
You can't see this if you just run:
evaluate 'Second'
as when 'evaluate' returns the results to the user, these "Parent Table" (or "Related") columns are not included.
Even so, these columns are certainly present.
When a table is converted to a row context, these related columns become available via RELATED.
See the following queries:
evaluate FILTER('Second', ISBLANK(RELATED(dimColour[Color])))
evaluate 'Second' order by RELATED(dimTime[Hour])
Similarly, when arguments to CALCULATE are used to update the filter context, these hidden "Related" columns are not ignored; hence, they can end up filtering First, in your example. You can see this, by using a function that strips the related columns, such as INTERSECT:
Test_ActuallyAlone = CALCULATE (
SUM ( First[Amount] ),
First[Alone] = "Y",
//This filter now does nothing, as none of the columns in Second
//have an impact on 'SUM ( First[Amount] )'; and the related columns
//are removed by the INTERSECT.
FILTER(
INTERSECT('Second', 'Second')
'Second'[Colour]="Red"
)
)
(See these resources that describe the "Expanded Table"
(this is an alternative but equivalent explanation of this behaviour)
https://www.sqlbi.com/articles/expanded-tables-in-dax/
https://www.sqlbi.com/articles/context-transition-and-expanded-tables/
)

sdo_relate giving a wrong query result

I have two geometry in two feature class ,one named "HY90299 " and the other named "hyboxsdo " ,the two geometry do not intersect .
but when i run a spatial query in oralce ,
"select sdo_relate(t.shape,g.shape ,'mask=ANYINTERACT') from HY90299 t,hyboxsdo g " ,
it return "true", the result is not correct .am I doing something wrong?
my oracle version is 11g
you can get the two geometry by
1.i put the two geometry into two shape file . you can get them from here
https://pan.baidu.com/s/1YQnwe8nstzgHOAwHgx9JGQ
2.or create the two geometry by wkt
â‘ MULTIPOLYGON (((-16.657423019000021 82.843477248999989, 16.710901260000014 66.242341995000004, 74.611375808999981 57.038061142000004, 111.18630027799998 67.126588820999984, -16.657423019000021 82.843477248999989)))
â‘¡MULTIPOLYGON (((60.839999999999975 26.569999999999993, 143.45000000000005 26.569999999999993, 143.45000000000005 55.75, 60.839999999999975 55.75, 60.839999999999975 26.569999999999993)))
Append
1.select * from user_sdo_geom_metadata where table_name='HY90299'
=============================
return "HY90299 SHAPE {{null,-180,180,0.001},{null,-90,90,0.001}} 4326"
2.select sdo_geom.validate_geometry_with_context(c.shape,0.000000005) from hy90299 c
select sdo_geom.validate_geometry_with_context(c.shape,0.001) from hy90299 c
=============================
all return "true"
3.select shape from hy90299
=============================
return "{2003,4326,null,{1,1003,1},{111.186300278,67.126588821,-16.657423019,82.843477249,16.71090126,66.242341995,74.611375809,57.038061142,111.186300278,67.126588821}}"
4.select sdo_geom.relate(t.shape,'determine',sdo_geometry(2003,4326,null, SDO_ELEM_INFO_ARRAY(1,1003,3),SDO_ORDINATE_ARRAY(60.840,26.570,143.450,55.750)),0.000000005) as spat_rel from HY90299 t
=============================
return "DISJOINT"
5.select sdo_geom.relate(t.shape,'determine',sdo_geometry(2003,4326,null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(60.840,26.570, 143.450,26.570, 143.450,55.750,60.840,55.750,60.840, 26.570)),0.000000005) as spat_rel from HY90299 t
=============================
return "OVERLAPBDYINTERSECT"
From the manual (https://docs.oracle.com/cd/B28359_01/appdev.111/b28400/sdo_operat.htm#SPATL1039), spatial operators "must always be used in a WHERE clause", not in the SELECT part of the query.
To use them (in the WHERE clause, as mentioned), they must be spatially indexed.
If you want to see the spatial relation, you can use one of the spatial functions - e.g:
select t.*,g.*, sdo_geom.relate(t.shape,'determine',g.shape,0.000000005) as spat_rel
from HY90299 t, hyboxsdo g
If you want you can add the function to the WHERE caluse as well, to filter the results - e.g. add in the above snippet:
where sdo_geom.relate(t.shape,'determine',g.shape,0.000000005) not in ('TOUCH','DISJOINT')
For a handful of geometries, you'll be fine. As the number of geometries grows, you must either use spatial indexes and add operator(s) in the WHERE clause, or device another way to filter the rows (e.g. by an attribute, id, etc) - spatial functions do not scale well.
You also have the responsibility to choose the TOLERANCE value that is appropriate for your data and query (I chose 0.000000005 as your shapes seem to have 8 significant decimals).
Last, BUT NOT LEAST, you'd want to make certain that your geometries are valid (again, at the appropriate tolerance).
HTH
APPEND:
1)
with HY90299 as (
select sdo_util.from_wktgeometry(
'MULTIPOLYGON (((-16.657423019000021 82.843477248999989, 16.710901260000014 66.242341995000004, 74.611375808999981 57.038061142000004, 111.18630027799998 67.126588820999984, -16.657423019000021 82.843477248999989)))'
) shape from dual ),
HYBOXSDO as (
select sdo_util.from_wktgeometry(
'MULTIPOLYGON (((60.839999999999975 26.569999999999993, 143.45000000000005 26.569999999999993, 143.45000000000005 55.75, 60.839999999999975 55.75, 60.839999999999975 26.569999999999993)))'
) shape from dual )
select sdo_geom.relate(t.shape,'determine',g.shape,0.000000005)
from HY90299 t,hyboxsdo g ;
The result is DISJOINT - also:
with HY90299 as (
select sdo_geometry(2003,4326,null, SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY(-16.657423019000021, 82.843477248999989, 16.710901260000014, 66.242341995000004, 74.611375808999981, 57.038061142000004, 111.18630027799998, 67.126588820999984, -16.657423019000021, 82.843477248999989))
shape from dual )
select sdo_geom.relate(t.shape,'determine',
sdo_geometry(2003,4326,null, SDO_ELEM_INFO_ARRAY(1,1003,3),SDO_ORDINATE_ARRAY(60.840,26.570,143.450,55.750))
,0.000000005) as spat_rel from HY90299 t
The result is, again, DISJOINT.
Your 'overlapbdyintersect' shouldn't be there - check the contents of your tables (since the difference in your two queries is the 'window' geometry, double check the hyboxsdo table).
2) You are wrong. Tolerance is essential. If you use sdo_geom.relate(t.shape,'determine',g.shape,2) -that is a tolerance of 2 meters- in the above queries, you will get TOUCH instead of DISJOINT (and by this, you can also tell that your geometries are roughly 2m apart). However, with these two geometries, you would never get OVERLAP.
3) A geometry's validity is directly related to the tolerance you use. Your geometries are valid (in 8 decimals) - I'm just saying that it will save you LOTS of headaches if you don't take it for granted. Never assume - check!
4) It doesn't matter how you put the geometries in the table. The only think you might want to consider (especially in production environments) is the number of decimals stored in the database - if your data make good sense at a precision of, say, 3 decimals, you'd be better off rounding or truncating your coordinates to that. Simpler coordinates lead to smaller footprint (database storage) and faster performance.

Power Bi - Filter on currency type

I have transactions in a variety of currencies in a Transaction table (columns TransactionAmount and TransactionCurrency), and also a related Currency table:
Using the column RateToEuro I have been able to convert all my transaction amounts, using a calculate column, into euros:
An example of what I would like: I want to select in my report filter 'Dollar' and then the Transaction amount should convert all original transaction amounts to dollars. So in my example above, the $2052 original trx amount will be 2052 also in the 'Transaction amount ($)' column.
[EDIT:]
Currently I have created measure that gets the filter value:
CurrencyFilter = IF(LASTNONBLANK('CurrencyFormat'[Name], 1) = "USD", "USD", "EUR")
And a calculated column that for each transaction calculates the converted transaction amount (depending on the report filter chosen):
TransactionAmountConverted = CALCULATE(VALUES(Transactions[TransactionAmount]) * (IF([CurrencyFilter] = "EUR", VALUES('Currency'[RateToEuro]), VALUES('Currency'[RateToDollar]))))
But for some reason the IF statement always returns TRUE (i.e. always uses the RateToEuro column).
Any hint or tip to point me in the right direction would be much appreciated!
Currently this is not possible in Power BI: it is not supported that a calculated column uses a slicer value.
A measure can be used to get the slicer value, but in this particular case (if one value for each row is required to be calculated), there is no solution possible unfortunately.

Calculated Measure in Analysis Services

The AdventureWorksDW has the construct of the Financial Reporting Fact table. I have a similar fact table where the fact contains only the FK to the dimension tables and a value. The measure gets it's context from an DimAccount dimension. Are there any code samples that show how to do a simple ratio in a calculated member between two measures of the AdventureWorks Financial Reporting sample?
So basically I would like to see say Total Long term Debt / Total Assets from AdventureWorksDW? What I need is the expression or MDX.
Thanks in advance.
Use a query like this:
with member [Account].[Accounts].[Balance Sheet].[Dept by Assets] as
IIf([Account].[Accounts].[Assets] <> 0,
[Account].[Accounts].[Long Term Liabilities] / [Account].[Accounts].[Assets],
null
)
,format_string = "0.00%"
select {
[Account].[Accounts].[Assets],
[Account].[Accounts].[Long Term Liabilities],
[Account].[Accounts].[Dept by Assets]
}
on columns,
{ [Measures].[Amount] }
on rows
from [Adventure Works]
You can define members in any hierarchy, not only in the measures. In the definition, you should use the parent member before the name of the new member, to tell AS the position in the hierarchy. This is more important for CREATE MEMBER in the cube calculation script than for WITH MEMBER, as it influences the position where the client tool will display it.

Resources