Check if column is null or blank in DAX - ssas

EVALUATE
FILTER
(
SUMMARIZE (
NATURALLEFTOUTERJOIN (
'Target_Category',
'Target_Form'
),
'Target'[Area],
'Target'[id],
'Target'[Target date],
'Target'[Target Time Range],
'Target_Category'[Origin],
'Target_Category'[Sectotion],
'Target'[Location],
'Target_Category'[Ethencity],
'Target_FormResponse'[Area Used],
'Target'[Description]
),
'Target'[id] = Value("111373268")
)
ORDEr BY 'Target'[Target Key]
I have the sample DAX query above. Is there away i can manipulate 'Target_FormResponse'[Area Used] such that if it is blank or empty, i return "No" otherwise if its not blank or empty i return "Yes".
In SSRS, i can do something like =IIF(Len(Fields!Form_Response.Value) > 0,"Yes","No") but i want to achieve this at the DAX query level.

If you are satisfied with adding an extra column that contains the "Yes" or "No" values, simple wrap the entire expression in a call to ADDCOLUMNS:
EVALUATE
ADDCOLUMNS (
FILTER (
SUMMARIZE (
NATURALLEFTOUTERJOIN ( 'Target_Category', 'Target_Form' ),
'Target'[Area],
'Target'[id],
'Target'[Target date],
'Target'[Target Time Range],
'Target_Category'[Origin],
'Target_Category'[Sectotion],
'Target'[Location],
'Target_Category'[Ethencity],
'Target_FormResponse'[Area Used],
'Target'[Description]
),
'Target'[id] = VALUE ( "111373268" )
),
"Area Used Yes/No", IF ( 'Target_FormResponse'[Area Used] > 0, "Yes", "No" )
)
ORDER BY 'Target'[Target Key]
If you want to get rid of the original column in the output, you'd have to use SELECTCOLUMNS instead, but unfortunately, you'd then have to specify the names of each of the columns you want to keep, so the code ends up a lot longer.

Related

Get the item with the highest count

Can you please help me to get the item with the highest count using DAX?
Measure = FIRSTNONBLANK('Table1'[ItemName],CALCULATE(COUNT('Table2'[Instance])))
This shows the First ItemName in the table but doesnt get the ItemName of the Highest Value.
Thanks
Well, it's more complicated than I would have wanted, but here's what I came up with.
There things that you are hoping to do that are not so straightforward in DAX. First, you want an aggregated aggregation ;) -- in this case, the Max of a Count. The second thing is that you want to use a value from one column that you identify by what's in another column. That's row-based thinking and DAX prefers column-based thinking.
So, to do the aggregate of aggregates, we just have to slog through it. SUMMARIZE gives us counts of items. Max and Rank functions could help us find the biggest count, but wouldn't be so useful for getting Item Name. TOP N gives us the whole row where our count is the biggest.
But now we need to get our ItemName out of the row, so SELECTCOLUMNS lets us pick the field to work with. Finally, we really want a value not a 1-column, 1-row table. So FirstNonBlank finishes the job.
Hope it helps.
Here's my DAX
MostFrequentItem =
VAR SummaryTable = SUMMARIZE ( 'Table', 'Table'[ItemName], "CountsByItem", COUNT ( 'Table'[ItemName] ) )
VAR TopSummaryItemRow = TOPN(1, SummaryTable, [CountsByItem], DESC)
VAR TopItem = SELECTCOLUMNS (TopSummaryItemRow, "TopItemName", [ItemName])
RETURN FIRSTNONBLANK (TopItem, [TopItemName])
Here's the DAX without using variables (not tested, sorry. Should be close):
MostFrequentItem_2 =
FIRSTNONBLANK (
SELECTCOLUMNS (
TOPN (
1,
SUMMARIZE ( 'Table', 'Table'[ItemName], "Count", COUNT ( 'Table'[ItemName] ) ),
[Count], DESC
),
"ItemName", [ItemName]
),
[ItemName]
)
Here's the mock data:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcipNSspJTS/NVYrVIZ/nnFmUnJOKznRJzSlJxMlyzi9PSs3JAbODElMyizNQmLEA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Stuff = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Stuff", type text}}),
#"Renamed Columns" = Table.RenameColumns(#"Changed Type",{{"Stuff", "ItemName"}})
in
#"Renamed Columns"

How to extract month-year from date from MDX Query

I need to filter data from Cube using Date without day inclusion.
Currently I am using following MDX query, that is fetching measures data starting from 1st day of the year and ending on the last day.
But, I only want to have Month-Year in date time at rows rather than DateTime with all days. ( Here my field for date is : [Period].[TransportDate] )
Following is the MDX Query.
SELECT
NON EMPTY
{
[Measures].[ConsignmentCount]
, [Measures].[CBM]
, [Measures].[LDM]
, [Measures].[Weight]
, [Measures].[Amount] } ON COLUMNS,
NON EMPTY
{ [Period].[TransportDate].Children } ON ROWS
FROM
(
SELECT
(
{ [Period].[YearAndMonth].[ConsignmentYear].&[2014]
, [Period].[YearAndMonth].[ConsignmentYear].&[2015] }
) ON COLUMNS
FROM [RebellOlap]
)
Above query fetching all records starting from 1st day till the last day of 2015. See attached image ( allRecords )
But I want somehow in following manner ( Required Data Set )
I want single column instead of Month and year. So
final data set should be
( e.g Date ( 07-2015 ), Amount,CBM, LDM, Num,. Consignments )
I know there's a way to extract only month and year from the whole date. But that works only for single date. What I want to have all dates must be filtered with the inclusion of month and Year and data should also corresponds to those dates accordingly. See above expected filtered data set.
Edit
WITH MEMBER [YearMo] AS
[Period].[ConsignmentYear].Currentmember.Name
+ "-" +
[Period].[ConsignmentMonth].Currentmember.Name
SELECT
NON EMPTY
{
[Measures].[ConsignmentCount]
, [Measures].[CBM]
, [Measures].[LDM]
, [Measures].[Weight]
, [Measures].[Amount]
} ON COLUMNS ,
NON EMPTY
(
{
[Period].[YearAndMonth].[ConsignmentMonth]
}
) ON ROWS
FROM
(
SELECT
(
{
[Period].[YearAndMonth].[ConsignmentYear].&[2014]
, [Period].[YearAndMonth].[ConsignmentYear].&[2015]
}
) ON COLUMNS
FROM [RebellOlap]
)
above produces result but without Year.
I want somehow to have year with month on the same columns.
so 01 would becomd 01-2014.
Could you help me
Results without concatenation
Either you have to create a new field as 'YYYY-mm' in the dimension view (cube design-sql view) or you can concatenate the year & month dimension attributes (Example below).
Example Code:
WITH MEMBER [YearMo] AS
[Period].[Monthly].Currentmember.Name
+ "-" + [Period].[YearAndMonth].Currentmember.Name
SELECT
NON EMPTY {[Measures].[ConsignmentCount], [Measures].[CBM], [Measures].[LDM], [Measures].[Weight], [Measures].[Amount]} ON COLUMNS
, NON EMPTY ( { [Period].[Monthly].[Year] } , { [Period].[YearAndMonth].[ConsignmentMonth] } ) ON ROWS
FROM
(
SELECT ( { [Period].[YearAndMonth].[ConsignmentYear].&[2014], [Period].[YearAndMonth].[ConsignmentYear].&[2015] } ) ON COLUMNS
FROM [RebellOlap]
)
Maybe try hosting the calculated member in a different hierarchy. I have guessed this [Forwarder].[Forwarder].[All] and you will need to adjust to a hierarchy that exists in your cube:
WITH MEMBER [Forwarder].[Forwarder].[All].[YearMo] AS
[Period].[Year].Currentmember.Name
+ "-" +
[Period].[Month].Currentmember.Name
SELECT
NON EMPTY
{
[Measures].[ConsignmentCount]
, [Measures].[CBM]
, [Measures].[LDM]
, [Measures].[Weight]
, [Measures].[Amount]
} ON COLUMNS ,
NON EMPTY
[Period].[Year].[Year]
*[Period].[Month].[Month]
*[Forwarder].[Forwarder].[All].[YearMo]
ON ROWS
FROM
(
SELECT
(
{
[Period].[YearAndMonth].[ConsignmentYear].&[2014]
, [Period].[YearAndMonth].[ConsignmentYear].&[2015]
}
) ON COLUMNS
FROM [RebellOlap]
)
Or if the above produces an error then you may need to create a measure first:
WITH
MEMBER [Measures].[YearMoString] AS
[Period].[Year].Currentmember.Name
+ "-" +
[Period].[Month].Currentmember.Name
MEMBER [Forwarder].[Forwarder].[All].[YearMo] AS
(
[Forwarder].[Forwarder].[All]
,[Measures].[YearMoString]
)
SELECT
NON EMPTY
{
[Measures].[ConsignmentCount]
, [Measures].[CBM]
, [Measures].[LDM]
, [Measures].[Weight]
, [Measures].[Amount]
} ON COLUMNS ,
NON EMPTY
[Period].[Year].[Year]
*[Period].[Month].[Month]
*[Forwarder].[Forwarder].[All].[YearMo]
ON ROWS
FROM
(
SELECT
(
{
[Period].[YearAndMonth].[ConsignmentYear].&[2014]
, [Period].[YearAndMonth].[ConsignmentYear].&[2015]
}
) ON COLUMNS
FROM [RebellOlap]
)

MDX Query WHERE Dimension = another Dimension

If I have two Dimensions: Origin and Destination how can I count the number of times Origin = Destination?
SELECT [Location] ON COLUMNS
FROM [DELIVERIES]
WHERE ( [Origin] = [Destination] )
[Origin] = [Destination] obviously isnt the answer...
The following code produces the correct result:
SELECT
SUM(Transfers) AS Same_Skill_Transfers
FROM (
SELECT
CONVERT(varchar(30),"[From VQ].[LOB].[LOB].[MEMBER_CAPTION]") As From_VQ,
CONVERT(varchar(30),"[To VQ].[LOB].[LOB].[MEMBER_CAPTION]") As To_VQ,
CONVERT(integer,"[Measures].[Transfers]") As Transfers
FROM
OPENQUERY(TRANSFERS,'
SELECT
{[Measures].[Transfers]} ON COLUMNS,
Filter(NonEmptyCrossjoin( [From VQ].[LOB].Members, [To VQ].[LOB].Members),
[From VQ].[LOB].[LOB].[Life Cycle].Properties(''Caption'') = [To VQ].[LOB].[LOB].[Life Cycle].Properties(''Caption'')
) ON 1
FROM
[Transfers]
WHERE (
[Date].[Date Hierarchy].[Month].[July 2014],
[From VQ].[Hierarchy].[AOB].[Consumer],
[From Agent].[Employee Id].&[612117]
)
')
) A
WHERE
To_VQ = From_VQ
Lets say I have a [FROM_VQ].[LOB] = "BOTH" and I want to include in the SUM when [FROM_VQ].[LOB] = "Both" and [TO_VQ].[LOB] is either A or B?
Your question is missing some info, but I'll take a stab and then update once you provide more info. I'm assuming that there are two dimensions, origin and destination, and that each of these dimensions have a location attribute.
In general, you can use a filter statement for this. If your location attribute has the same key in each dimension, you can do this:
select [Origin].[Location].children on 0,
Filter(NonEmptyCrossjoin( [Origin].[Location].Children, [Destination].[Location].Children),
[Origin].[Location].Properties('Key') = [Destination].[Location].Properties('Key')
) on 1 from [DELIVERIES]
If the keys aren't the same, but the label you see for the field is you can switch Key for Caption.
Here's an example where someone did this with dates.

Case, Select conditional requirments

Operating in an Excel query, I need a conditional statement that will read one field, and based on that value, set another field to a minus (or not).
My SQl code is as follows:
SELECT "_bvSTTransactionsFull".txdate,
SUM("_bvSTTransactionsFull".debit) AS 'TOTALDebit',
SUM("_bvSTTransactionsFull".credit) AS 'TOTALCredit',
SUM("_bvSTTransactionsFull".tax_amount) AS 'TOTALTax_Amount',
SUM("_bvSTTransactionsFull".VALUE) AS 'TOTALValue',
SUM("_bvSTTransactionsFull".actualvalue) AS 'TOTALActualValue',
SUM("_bvSTTransactionsFull".actualsalesvalue) AS 'TOTALActualSalesValue',
SUM("_bvSTTransactionsFull".profit) AS 'TOTALProfit'
FROM sqlschema.dbo."_bvSTTransactionsFull" "_bvSTTransactionsFull"
WHERE ( "_bvSTTransactionsFull".txdate >=?
AND "_bvSTTransactionsFull".txdate <=? )
GROUP BY "_bvSTTransactionsFull".txdate,
"_bvSTTransactionsFull".description
HAVING ( "_bvSTTransactionsFull".description LIKE 'POS Sale' )
OR ( "_bvSTTransactionsFull".description LIKE 'POS Return' )
ORDER BY "_bvSTTransactionsFull".txdate
I need the select query to look at a field named "ActualQuantity" (in the table "_bvSTTransactionsFull") and if this field is <0 , then Tax_Amount = -(Tax_Amount), or if ActualQuantity >=0, then Tax_Amount = Tax_Amount.
Please note the query is "summed", so I assume this conditional aspect needs to be handled before summation takes place. The query summates approximately 100 000 records into daily totals.
SELECT "_bvSTTransactionsFull".txdate,
SUM("_bvSTTransactionsFull".debit) AS 'TOTALDebit',
SUM("_bvSTTransactionsFull".credit) AS 'TOTALCredit',
SUM(case when "_bvSTTransactionsFull".ActualQuantity >= 0
then "_bvSTTransactionsFull".tax_amount
else - "_bvSTTransactionsFull".tax_amount
end) AS 'TOTALTax_Amount',
SUM("_bvSTTransactionsFull".VALUE) AS 'TOTALValue',
SUM("_bvSTTransactionsFull".actualvalue) AS 'TOTALActualValue',
SUM("_bvSTTransactionsFull".actualsalesvalue) AS 'TOTALActualSalesValue',
SUM("_bvSTTransactionsFull".profit) AS 'TOTALProfit'
FROM sqlschema.dbo."_bvSTTransactionsFull" "_bvSTTransactionsFull"
WHERE ( "_bvSTTransactionsFull".txdate >=?
AND "_bvSTTransactionsFull".txdate <=? )
GROUP BY "_bvSTTransactionsFull".txdate,
"_bvSTTransactionsFull".description
HAVING ( "_bvSTTransactionsFull".description LIKE 'POS Sale' )
OR ( "_bvSTTransactionsFull".description LIKE 'POS Return' )
ORDER BY "_bvSTTransactionsFull".txdate
If ActualQuantity might be zero but taxAmount in the same row is zero too you can use sign function to change sign of tax_amount:
sign(ActualQuantity) * tax_amount
UPDATE:
So I gather that MS Query has problems using parameters in a query that cannot be displayed graphically. Workaround is to replace parameters with some constants, save workbook as XML and change constants to "?". There is a link showing VBA code which does replacement on-site, but you will have to figure out how it works as I don't know VBA that much.
UPDATE 2:
On the other hand the easiest way out is to create view in your database.

MDX - TopCount plus 'Other' or 'The Rest'

I have created an MDX query which calculates the TOP 10 ZipCodes (according to my Patient Stay measure) as such:
WITH
MEMBER [Discharge Date].[Y-M-D].[ Aggregation] AS 'AGGREGATE( EXISTING { [Current Month] } )', SOLVE_ORDER = 0
SELECT
NON EMPTY { [Measures].[Patient Stays] }
ON COLUMNS,
TOPCOUNT({ ORDER( HIERARCHIZE( { [Patient].[ByZipcode].[All].CHILDREN } ), ( [Measures].[Patient Stays] ), BDESC ) }, 10)
ON ROWS
FROM [Patient Stay]
WHERE ( [Discharge Date].[Y-M-D].[ Aggregation], [Facility].[ByAffiliation].CURRENTMEMBER, [Facility].[ByRegion].CURRENTMEMBER )
This query is used to populate a PerformancePoint 100% Stacked Bar chart. The client has asked that since this is a !00% based chart, we lump the rest of the zip codes into an "Other" field, such that there should be 11 values: one for each of the top 10, and an eleventh which is a sum of the remaining Zip Codes.
I am an extreme novice to MDX, but this doesn't souund like it should be impossible. Does anyone have any ideas or suggestions?
I'll do my best with untested code, so here goes:
WITH
MEMBER [Discharge Date].[Y-M-D].[ Aggregation] AS 'AGGREGATE( EXISTING { [Current Month] } )', SOLVE_ORDER = 0
SET [Top10ZipCodes] AS
(TOPCOUNT({ ORDER( HIERARCHIZE( { [Patient].[ByZipcode].[All].CHILDREN } ), ( [Measures].[Patient Stays] ), BDESC ) }, 10))
MEMBER [Patient].[ByZipCode].[OtherZipCodes] AS
(AGGREGATE({EXCEPT([Patient].[ByZipCode].Members, [Patient].[ByZipCode].[Top10ZipCodes])}))
SELECT
NON EMPTY { [Measures].[Patient Stays] }
ON COLUMNS,
{[Top10ZipCodes], [Patient].[ByZipCode].[OtherZipCodes]}
ON ROWS
FROM [Patient Stay]
WHERE ( [Discharge Date].[Y-M-D].[ Aggregation], [Facility].[ByAffiliation].CURRENTMEMBER, [Facility].[ByRegion].CURRENTMEMBER )
What this does is creates a set of your top 10 ZIP codes, and then aggregates (different than sum!!!) all the ZIP codes, with the exception of your top 10.
Also, if this is a common set (top 10 ZIP codes), you may want to make a set on the cube, where you can reuse it ad nauseum, without having to change every MDX query you have.
Cheers,
Eric