I am using the following statement to get a result table:
EVALUATE
(
CALCULATETABLE
(
ADDCOLUMNS (
'Case',
"Casenumber", RELATED( 'CaseDetails'[nr]),
),
'Case'[Date] <= value(#dateto) )
)
However, I want to only get one record pr casenumber. In SQL I would solve this with a GROUP BY statement, but how should I do this in DAX? Case also has a dimkey, so several cases with the same casenumber can have different dimkeys.
Try this:
EVALUATE
CALCULATETABLE(
SUMMARIZE(
Case
,<comma-separated list of fields from Case you want>
,"CaseNumber"
,RELATED(CaseDetails[nr])
)
,Case[Date] <= VALUE(#dateto)
)
SUMMARIZE() takes a table as its first argument, then a comma-separated list of fields from that table and any tables that it is related to where it is on the many side (thus in a star schema, SUMMARIZE()ing the fact table will allow you to refer directly to any dimension table field), followed by a comma-separated list of , pairs where is a quoted field name and is a scalar value which is evaluated in the row context of the table in the first argument.
If you don't need to rename CaseDetails[nr], then the query would look like this (just for an illustrative example):
EVALUATE
CALCULATETABLE(
SUMMARIZE(
Case
,<comma-separated list of fields from Case you want>
,CaseDetails[nr]
)
,Case[Date] <= VALUE(#dateto)
)
In such a query, all fields will come through with column headings in the format of 'table'[field], so there is no ambiguity if you have identical field names in multiple related tables.
Edit to address new information in original:
SUMMARIZE(), just like SQL's GROUP BY clause will not eliminate distinct values from the resultset. If there is a field that is a higher cardinality than the field you want to group by, you will always see duplicates.
Is your [DimKey] necessary in the resultset? If yes, then there's no way to decrease the size of your resultset smaller than the number of distinct values of [DimKey].
If [DimKey] is unnecessary, simply omit it from the list of fields in SUMMARIZE().
If you want only a specific [DimKey], e.g. the most recent (assuming it's an IDENTITY field and the max value is the latest), then you can bring it in with another ADDCOLUMNS() wrapped around your current SUMMARIZE():
EVALUATE
ADDCOLUMNS(
SUMMARIZE(
Case
,<comma-separated list of fields from Case except for [DimKey]>
,"CaseNumber"
,RELATED(CaseDetails[nr])
)
,"MaxDimKey"
,CALCULATE(MAX(Case[DimKey]))
)
Related
I have 3 dimensions tables and one fact Table Sales
DimCalendar (Fields Year/Month/Day/Week)
DimCountry (Field : CountryName)
DimManager (Field ManagerName)
FctSales (Field : Amount)
I want to create a measure to Sum the Amount of the Sales (FctSales) and filter only to the fields of the tables DimCalendar and DimCountry.
After research, i was thinking about the function AllExcept, like :
CALCULATE(SUM(Sales[Amt]);ALLExcept(Sales;Country[Country];Calendar[Year]...)
but if i do that, i will have to write every columns of the table Calendar and Table Country in the AllExcept, i am wondering if there is another solution.
Maybe using REMOVEFILTERS() to remove every filter and then put back the filters over DimCountry and DimCalendar might work?
CALCULATE (
SUM ( Sales[Amt] );
REMOVEFILTERS ();
VALUES( DimCountry[CountryName] );
VALUES( DimCalendar[Date] )
)
DimCalendar[Date] should be the column used for the relationship with Sales.
This measure first evaluates the filter arguments in the current filter context.
Using as filter the columns used for the relationships guarantees that whatever the column used for filtering this would be mapped over the relationship.
Then, the REMOVEFILTERS() will remove any existing context filter and eventually the filter arguments evaluated during the first step will be applied, putting back any filtering that was set over DimCalendar and DimCountry.
iam trying to create a measure with a filter.
i have fields TPLNR and TXT04. A TPLNR contains double/triple records with different TXT04 values.
TPLNR 4OR-TTE-A-TY09159 have 3 different values in TXT04. iam trying to create a measure that if a TPLNR has the value DLFL i dont want to see the other 2 values also in my output. in this case i dont want to see the TPLNR 4OR-TTE-A-TY09159 in my visual and table drill through. is it possible to create such measure?
enter image description here
could someone help me with this?
In order to do so, I suggest you use the filter functionality offered by PowerBI, in this way you won't need a measure just to filter your data.
In order to make filtering easier, I suggest you use a flag to specify what to include or exclude, you can calculate it in 3 ways.
in your source, so it's already ready to use in PowerBI
Using M (Power Query)
Reference the existing table (which makes a sort of copy of it)
filter it to include only the rows you want to include or exclude
join with the original table and create you "flag" by managing missing values (a sort of COALESCE)
specify that this "clone" table must not be loaded into the model
Using DAX calculated column
The formula might look like the one below
MyFilterFlag =
CALCULATE (
CONTAINSROW ( VALUES ( 'Table'[TXT04] ), "DLFL" ),
ALLEXCEPT ( 'Table', 'Table'[TPLNR] )
)
The formula checks for the available values in the column TXT04, by keeping as a filter only TPLNR, in practice it behaves as a group by
If you need more conditions just add them to the checked expression (&& = AND)
CALCULATE (
CONTAINSROW ( VALUES ( 'Table'[TXT04] ), "DLFL" )
&& CONTAINSROW ( VALUES ( 'Table'[INACT] ), "X" )
,ALLEXCEPT ( 'Table', 'Table'[TPLNR] )
)
I have table[Table 1] having three columns
OrganizationName, FieldName, Acres having data as follows
organizationname fieldname Acres
ABC |F1 |0.96
ABC |F1 |0.96
ABC |F1 |0.64
I want to calculate the sum of Distinct values of Acres
(eg: 0.96+0.64) in DAX.
One of the problems with doing what you want is that many measures rely on filters and not actual table expressions. So, getting a distinct list of values and then filtering the table by those values, just gives you the whole table back.
The iterator functions are handy and operate on table expressions, so try SUMX
TotalDistinctAcreage = SUMX(DISTINCT(Table1[Acres]),[Acres])
This will generate a table that is one column containing only the distinct values for Acres, and then add them up. Note that this is only looking at the Acres column, so if different fields and organizations had the same acreage -- then that acreage would still only be counted once in this sum.
If instead you want to add up the acreage simply on distinct rows, then just make a small change:
TotalAcreageOnDistinctRows = SUMX(DISTINCT(Table1),[Acres])
Hope it helps.
Ok, you added these requirements:
Thank You. :) However, I want to add Distinct values of Acres for a
Particular Fieldname. Is this possible? – Pooja 3 hours ago
The easiest way really is just to go ahead and slice or filter the original measure that I gave you. But if you have to apply the filter context in DAX, you can do it like this:
Measure =
SUMX(
FILTER(
SUMMARIZE( Table1, [FieldName], [Value] )
, [FieldName] = "<put the name of your specific field here"
)
, [Value]
)
I have two tables, one called STUDENTS and the other CLASSES. I have to select all the students that are from the same class of one student, and this student has his own number id, and through this number id that I have to select everything.
TABLE STUDENTS
nr_rgm
nm_name
nm_father
nm_mother
dt_birth
id_sex
TABLE CLASSES
cd_class
nr_schoolyear
cd_school
cd_degree
nr_series
cd_class
cd_period
So I tried something like that :
SELECT count(*) FROM students, classes WHERE id_sex = 'M' AND
cd_class = (SELECT cd_class FROM classes WHERE nr_rgm = '12150');
But then it points an error, and the error is the follow :
single-row subquery returns more than one row
So, how can I make this work ?
you should use "in" and not "=" when applying subselects.
I think what you really would want to do is to simply join the two tables together rather than issuing a sub select:
SELECT count(*)
FROM students s, classes c
WHERE s.id_sex = 'M' AND c.nr_rgm = '12150' AND s.cd_class = c.cd_class;
This way you just tell the database: Please count all the occurrences where my students.id_sex = 'M' and my classes.nr_rgm = '12150' AND all found studends.cd_class match those of my classes.cd_class.
The reason why your statement above fails is because the ordinary = operation, when not used in a join, will only expect one single value, like you do with s.id_sex='M' while your statement returns multiple values. To cope with that you have to use the IN operator which operates on lists.
However, you can and will achieve the very same with just joining the two tables together, and it will be much more efficient on bigger data sets.
One more note to the example above. If classes.nr_rgm is a field of data type NUMBER, don't use the ' around the value 12150 as it will lead to implicit type conversion. With other words, '12150' is a string and will have to be converted to NUMBER first before doing a comparison.
As seen below there is a simple join between my Tables A And B.
In addition, there is a condition on each table which is combined with Or operator.
SELECT /*+ NO_EXPAND */
* FROM IIndustrialCaseHistory B ,
IIndustrialCaseProduct A
where (
A.ProductId IN ('9_2') OR
contains(B.KeyWords,'%some text goes here%' ) <=0
)
and ( B.Id = A.IIndustrialCaseHistoryId)
on ProductId defined a b-tree index and for KeyWords there is a function index.
but I dont know why my execution plan dose not use these indexes and performs table access full?
as I found in this URL NO_EXPAND optimization hint could couse using indexes in execution plan(The NO_EXPAND hint prevents the cost-based optimizer from considering OR-expansion for queries having OR conditions or IN-lists in the WHERE clause ). But I didn't see any use of defined indexes
whats is oracle problem with my query?!
Unless there is something magical about the contains() function that I don't know about, Oracle cannot use an index to find a matching value that leads with a wildcard, i.e. a text string value within a varchar2 column but not starting in the first position with that value. [OR B.KeyWords LIKE'%some text goes here%' -- as opposed to -- OR B.KeyWords LIKE'Some text starts here%' -- optimizable via index.] The optimizer will default back to the full table scan in that case.
Also, although it may not be material, why use IN() if there is only one value in the list? Why not A.ProductId = '9_2' ?