GroupBy and aggregate in DAX - powerbi

I'm new to DAX queries and trying to create a DAX query equivalent to following SQL query.
SELECT Year, Company, SUM(Actual Sales) as Actual, SUM(Planned Sales) as Planned
FROM Sales
GROUP BY Year, Company
I'm not able to take aggregate of multiple columns after groupby in DAX. How can I resolve this?

There are actually a few ways in Power BI to do this kind of aggregation. Here are three different options with slightly different results from each other.
Option 1: Query Editor
In the query editor window, select Transform -> Group By...
... and configure it as shown below (make sure to click the Advanced option).
This results in the below. Note - this replaces the starting table.
Option 2: Measures
In the regular window (not the query editor used in option 1), click on Modeling -> New Measure...
... to create two measures using the formulas below.
Actual = SUM(Sales[Actual Sales])
Planned = SUM(Sales[Planned Sales])
Once those measures are created, a visual (a matrix in this case) can be created with the desired headers and values.
Option 3: Columns
Similarly to option 2, click on Modeling -> New Column...
... to create two columns using the formulas below.
Actual = CALCULATE(
SUM(Sales[Actual Sales]),
FILTER(
Sales,
Sales[Year] = EARLIER(Sales[Year]) &&
Sales[Company] = EARLIER(Sales[Company])
)
)
Planned = CALCULATE(
SUM(Sales[Planned Sales]),
FILTER(
Sales,
Sales[Year] = EARLIER(Sales[Year]) &&
Sales[Company] = EARLIER(Sales[Company])
)
)
Now the aggregations are in columns that can be used report visuals.

Related

Power BI Min date of each category

I am familiar with SQL and I can write a query to return results of a query to Select MIN(Date), MAX(Date), SUM(quality) and GROUP BY. However, I am new to Power BI and DAX and find it difficult to do the same on Power BI. Below is my situation.
These tables on Power BI:
Dim_ManefactureDate
Dim_ReleaseDate
Fact_OrderID
Table Relationships
Adding a table visualization to a new page to show data from three tables above, data is showing as below:
Under Values of Visualizations, when selecting SUM over Netweight, it automatically summarizes expected Netweight. However, for ManufactureDate and ReleaseDate, when selecting Earliest then Power BI table shows unexpected 1/01/1900 values like this:
I expect earliest date of each OrderID as below:
I have also tried to use a DAX function to create a new column but it gets error
ManufactureDate_Earliest =
VAR Sum_Netweight = SUM(Fact_OrderID[NetWeight])
VAR GroupBy_OrderID = GROUPBY(Fact_OrderID,Fact_OrderID[OrderID])
RETURN
CALCULATE(
MIN(RELATED(Dim_ManufactureDate[DateBK]))
)
Thank you very much for your help
Due to getting values from relationship tables, used these measured and solved the issue
ManufactureDate_Earliest =
CALCULATE(
MIN(ManufactureDate[DateBK]),
CROSSFILTER(Fact_Order[ManufactureDate_DateSK], ManufactureDate[DateSK], BOTH)
)
ReleaseDate_Earliest =
CALCULATE(
MIN(ReleaseDate[DateBK]),
CROSSFILTER(Fact_Order[ReleaseDate_DateSK], ReleaseDate[DateSK], BOTH)
)

Power BI Visual Filter Not Filtering All Other Visuals

I have a date table that is used to populate a date slicer. The date slicer filters all other filters on the page but one. The one it doesn't filter has a one-to-many relationship back to the date table.
However, when I use the data from table two as an axis (Date and Hour) it actually displays all date/hours from the entire table but doesn't restrict the date/hour range to that of the parent date table (table one). Thoughts on how I can achieve this without using merge tables (preferable in DAX)?
In SQL Server I would do the following to achieve this output:
select fc1.calendardatewithtime, totaltable.total
from FiscalCalendarWithTime fc1
cross apply (
select top(1) count(distinct id) total
from ActionDetail ad1
where ad1.upgraded_on=fc1.calendardatewithtime and ad1.status=3
)as totaltable
where exists ( select 1 from dbo.FiscalCalendarTable fc2 where fc2.calendardate=fc1.calendardate and fc2.fiscalweek=1 )
order by fc1.calendardatewithtime asc;
Where calendardatewithtime is the date with time field that I would use as the axis and totaltable.total is the value I would display as the graph total.
My Date Slicer code:
SpecialDateDropdown =
VAR _datetable = FiscalDGCalendar
VAR _today = TODAY()
VAR _yesterday = TODAY()-1
VAR CurrentFiscalWeek = calculate(min(FiscalCalendar[fiscal_week]),filter(FiscalCalendar,format(now(),"mm/dd/yyyy")=format(FiscalCalendar[fiscal_date],"mm/dd/yyyy")))
VAR CurrentFiscalPeriod = calculate(min(FiscalCalendar[fiscal_period]),filter(FiscalCalendar,format(now(),"mm/dd/yyyy")=format(FiscalCalendar[fiscal_date],"mm/dd/yyyy")))
VAR CurrentFiscalQuarter = calculate(min(FiscalCalendar[fiscal_quarter]),filter(FiscalCalendar,format(now(),"mm/dd/yyyy")=format(FiscalCalendar[fiscal_date],"mm/dd/yyyy")))
VAR CurrentFiscalYear = calculate(min(FiscalCalendar[fiscal_year]),filter(FiscalCalendar,format(now(),"mm/dd/yyyy")=format(FiscalCalendar[fiscal_date],"mm/dd/yyyy")))
RETURN UNION(
ADDCOLUMNS(FILTER(_datetable,[fiscal_date]=_today),"Period","Today","Order",1),
ADDCOLUMNS(FILTER(_datetable,[fiscal_date]=_yesterday),"Period","Yesterday","Order",2),
ADDCOLUMNS(FILTER(_datetable,[fiscal_year]=CurrentFiscalYear&&[fiscal_week]=CurrentFiscalWeek),"Period","Current Fiscal Week","Order",3),
ADDCOLUMNS(FILTER(_datetable,[fiscal_year]=CurrentFiscalYear&&[fiscal_week]=CurrentFiscalWeek-1),"Period","Prior Fiscal Week","Order",4),
ADDCOLUMNS(FILTER(_datetable,[fiscal_year]=CurrentFiscalYear&&[fiscal_period]=CurrentFiscalPeriod),"Period","Current Fiscal Month","Order",5),
ADDCOLUMNS(FILTER(_datetable,[fiscal_year]=CurrentFiscalYear&&[fiscal_period]=CurrentFiscalPeriod-1),"Period","Prior Fiscal Month","Order",6),
ADDCOLUMNS(FILTER(_datetable,[fiscal_year]=CurrentFiscalYear&&[fiscal_quarter]=CurrentFiscalQuarter),"Period","Current Fiscal Quarter","Order",7),
ADDCOLUMNS(FILTER(_datetable,[fiscal_year]=CurrentFiscalYear),"Period","Current Fiscal Year","Order",8),
ADDCOLUMNS(_datetable,"Period","Custom Date Range","Order",9)
)
And this is how I am gathering my totals so the only piece I am missing is how to visually display only a specific date range:
CALCULATE(
IF(
ISBLANK(DISTINCTCOUNT(ActionHistoryDetail[id])),0,DISTINCTCOUNT(ActionHistoryDetail[id])
),ActionHistoryDetail[status]=3,USERELATIONSHIP(FiscalCalendar[fiscal_date],fiscalcalendarwithtime[CalendarDate]),USERELATIONSHIP(fiscalcalendarwithtime[CalendarDateWithTime],ActionHistoryDetail[upgraded_on])
)
You can group the slicers in a single family, as all the slicers will have the same values(if values are the same). Then you can hide the second slicer behind the first slicer.
As you can see Date Table doesn't filter DATA TABLE as I haven't grouped them yet.
Now I got to View in the ribbon and select the sync slicers option and then go to Advanced Controls and group both of the slicers as A.
View >> Sync Slicers >> Advanced Options
Now as both of the slicers are grouped, when I sleect the Year from the Data Table slicer it filters the DATA TABLE table too.
Now just hide the other slicer.
If this answer helped you, then mark it as answer. Thanks.
You should check your relationships.
Make sure you have a date table mapping to your main table.

Power BI slicer OR condition

The interaction between two slicers in Power BI gives me output with AND condition.
Example: If I selected the year 2020 and company ABC, the output would be all the data from company ABC in the year 2020.
But I want the two slicers to work with OR condition.
I have used this Dax
Include = (MAX(Table1[Column1]) = SELECTEDVALUE(Col1[Column1])) +
(MAX(Table1[Column2]) = SELECTEDVALUE(Col2[Column2]))
But the problem with above Dax I have not selected anything in slicer ( ALL by default) it is showing me a blank visual. What am I doing wrong?
let me guess you have a table "or_slicer_main_table" with Year, Company and some other columns. Now create 2 new table where the first one will contain the distinct list of Year from table "or_slicer_main_table" and the second one will contain distinct Company list from that same table.
New custom Table 1:
or_slicer_year_list =
SELECTCOLUMNS(
'or_slicer_main_table',
"YEAR", 'or_slicer_main_table'[year]
)
New custom Table 2:
or_slicer_company_list =
SELECTCOLUMNS(
'or_slicer_main_table',
"company", 'or_slicer_main_table'[company]
)
Do not establish any relation between those 3 tables.
Step-1: Create Year slicer using the newly created "or_slicer_year_list" table.
Step-2: Create Company slicer using the newly created "or_slicer_company_list" table.
Step-3: Create these following 5 measures in your table "or_slicer_main_table"
1.
year_current_row = max('or_slicer_main_table'[year])
2.
year_selected_in_slicer = SELECTEDVALUE(or_slicer_year_list[YEAR])
3.
company_current_row = max('or_slicer_main_table'[company])
4.
company_selected_in_slicer = SELECTEDVALUE(or_slicer_company_list[company])
5.
show_hide =
if(
[year_selected_in_slicer] = [year_current_row]
|| [company_selected_in_slicer] = [company_current_row],
1,
0
)
Now you have all instruments ready for play. Create your visual using columns from the table "or_slicer_main_table"
Final Step: Now just add a visual level filter for the measure "show_hide" and set value will show only when "show_hide = 1".
The final output will be something like below image-
Can you try using "IN VALUES" instead of "SELECTEDVALUE"
So your DAX should be
Include = (MAX(Table1[Column1]) IN VALUES (Col1[Column1])) +
(MAX(Table1[Column2]) IN VALUES (Col2[Column2]))
SELECTEDVALUE function returns the result only if single value is selected in slicer in case of multiple selection it will return Blank(). Thats in the case when nothing is selected (which is similar to all selected) has multiple values in set and so SELECTEDVALUE fucntion will return Blank(). This can be handled by using "IN VALUES" function which can return a set of all selected values.

Dax - dynamic attribute value based on filter parameter

I need to create a calculated column that is based on another column but depends on the date filter the report is run for.
If the item is own for more than a year it is 'Comparable' if less than a year it is 'Non Comparable'.
I have Item, DateOfPurchase in T1 and Date in T2 (Period table)
I have come up with DAX using today() but it only works if we report on today's date.
This didn't work (no idea why)
=if( dateadd( 'Item'[PurchaseDate],1,year)<today(),"Comp","Non-Comp")
This worked but only for current period
=DATEDIFF('Item'[PurchaseDate],today(),MONTH)
= if('Item'[DateDiff]>12,"Comp","NonComp")
However, I can not use that column when running report for a different period, because attribute is not valid for prior periods.
Since calculated columns are computed only once, when the table is processed/refreshed, you cannot use a calculated column for your scenario.
Instead, consider using a disconnected parameter table. In your case, this would be a table with 1 column and just 2 rows: "Comp" and "NonComp". You can create this as a calculated table like so:
ParameterTable = DATETABLE("Value", STRING, {{"Comp", "NonComp"}})
Based on what the user selects on this table - which you can find using SELECTEDVALUE(ParameterTable[Value]) - you apply the relevant logic in a measure instead:
BaseMeasure =
// Whatever you are trying to calculate
SUM(Item[Amount])
Measure =
// This measure will respect the user selection (Comp / NonComp) and the current period:
VAR compValue = SELECTEDVALUE(ParameterTable[Value])
VAR today = MAX('Date'[Period])
RETURN
SWITCH(
compValue,
"Comp", CALCULATE( [BaseMeasure] , DATEDIFF('Item'[PurchaseDate], today, MONTH) > 12),
"NonComp", CALCULATE( [BaseMeasure] , DATEDIFF('Item'[PurchaseDate], today, MONTH) < 12),
[BaseMeasure] // Fallback, in case user didn't select Comp/NonComp
)
If you have multiple base measures in your report, you will need to implement this pattern for each of your base measures.

Power BI Rank within Matrix Visual

I've spent many weeks trying to get this to work including a posting at another site. No luck. Not sure what I'm missing.
The following code gets me the table of data that I need. However, I want just the "rank" value and I want it for each row within a matrix visual.
First some background, the PowerBI page has slicers on dates and "base" product. Any given product may be sold in multiple countries. All carry the same base product suffix with a country-specific prefix.
The matrix in question displays several aspects of all the product variants for the selected base product. I want to show where each variant ranks (unit sales) within its country.
VAR tblCountrySales =
SUMMARIZE (
FILTER(
tblSalesUnits,
RELATED(tblProducts[Country])="US"
),
tblProducts[ProdID],
"Total Sales", SUM ( tblSalesUnits[Units] )
)
RETURN
ADDCOLUMNS (
tblCountrySales,
"ProductRank", RANKX ( tblCountrySales, [Total Sales] )
)
Is there a way to either pull just the rank for a single product from the above code, or, better yet, a DAX pattern that will get me the rank by unit sales of each product variant within its respective country?
I've use these statements to successfully get the product ID and country for each row within the visual.
VAR ProdSales = SUM(tblSales[Units])
VAR ProdCountry = SELECTEDVALUE(tblProducts[Country])
Any help is greatly appreciated. I assume I'm missing something with row context within the visual as a simple COUNTROWS on the table expressions above always returns "1". Being new to PowerBI and DAX I'm still trying to grasp the nuances of filter and row contexts.
The products table contains data like...
ProdID.....BaseID....Name...Country
7190...........7190.....xxxx.....US
150207190......7190.....XXXX....Panama
241807190......7190.....xxxx.....Spain
The sales table contains data like...
ProdID......SalesMonth......Units.....USD
7190........July 2010.......4563....$23491.00
150207190...July 2010.......2543....$16235.00
241807190...July 2010.......1263....$8125.00
There is a dates table as well that links the SalesMonth to the usual selection of date display formats. The two tables above are linked via ProdID, though the visuals are sliced by the BaseID. I'd attach a picture, but don't have permissions to do so.
With some more tinkering I found this solution.
Country Rank =
VAR ProdSales = SUM(tblSales[Units])
VAR ProdCountry = SELECTEDVALUE(tblProducts[Country])
VAR tblCountrySales =
SUMMARIZE (
FILTER(
ALLEXCEPT(tblProducts,tblProducts[BaseID]),
tblProducts[Country]=ProdCountry
),
tblProducts[ProdID],
"Total Sales", SUM ( tblSales[Units] )
)
RETURN
IF(ProdSales>0,COUNTROWS(FILTER(tblCountrySales,[Total Sales]>ProdSales))+1,BLANK())