I have 2 columns, Status and Date. The "Status" column contains three values ('Past Due', 'Soon Due', 'Calibrated').
I would like to display the most recent month name calculated for each of these status categories separately. Specifically, I would like to create a table visual where we have 3 different columns with the names "Past Due", "Soon Due", and "Calibrated". These columns display the most recent month name for dates corresponding to each status category, as outlined in the screenshots below.
Sample Input:
Desired Output:
FORMAT([DateField], "MMM") is the key DAX function here.
I've outlined the 3 measures below that should give you the result you want. Replace "Table1" with your table name.
Past Due
Past Due = CALCULATE(FORMAT(MAX(Table1[Date]), "MMM"), Table1[Status] = "Past Due")
Soon Due
Soon Due = CALCULATE(FORMAT(MAX(Table1[Date]), "MMM"), Table1[Status] = "Soon Due")
Calibrated
Calibrated = CALCULATE(FORMAT(MAX(Table1[Date]), "MMM"), Table1[Status] = "Calibrated")
Measures in Table
Related
Im trying to calculate the Time Weigthed Return for a portfolio of stocks. The formula is:
I have the following data:
Im calculate the TWR (time weigthed return) in Power Bi as:
TWR = productx(tabel1;TWR denom/yield+1)
The grey and blue marked/selected fields are individual single stock. Here you see the TWR for the grey stock is = 0,030561631 and for the blue TWR = 0,012208719 which is correct for the period from 09.03.19 to 13.03.19.
My problem is, when im trying to calculate the TWR for a portfolio of the two stocks, it takes the product og every row. In the orange field I have calculated the correct result in excel. But in Power BI it takes the product of the grey and blue stocks TWR: (0,0305661631 * 0,012208719) = 0,03143468 which is incorrect.
I want to sum(yield for both stocks)/sum(TWRDenominator for both stocks) for both stocks every single date, such that I not end up with two rows (one for each stock) but instead a common number every date for the portfolio.
I have calculated the column TWR denom/yield -1 in a measure like this:
twr denom/yield-1 = CALCULATE(1+sumx(tabel1;tabel1(yield)/sumx(tabel1;tabel1[TwrDenominator])))
How can I solved this problem?
Thank you in advance!
This is one solution to your question but it assumes the data is in the following format:
[Date] | [Stock] | [TWR] | [Yield]
-----------------------------------
[d1] | X | 12355 | 236
[d1] | y | 23541 | 36
[d2] ... etc.
I.e. date is not a unique value in the table, though date-stock name will be.
Then you can create a new calculated table using the following code:
Portfolio_101 =
CalculateTable(
Summarize(
DataTable;
DataTable[Date];
"Yield_over_TWR"; Sum(DataTable[Yield])/Sum(DataTable[TWR_den])+1
);
Datatable[Stock] in {"Stock_Name_1"; "Stock_Name_2"}
)
Then in the new Portfolio_101 create a measure:
Return_101 =
Productx(
Portfolio_101;
Portfolio_101[Yield_over_TWR]
)-1
If using your data I en up with the following table, I have created three calculated tables, one fore each stock and a third (Portfolio_103) with the two combined. In addition I have a calendar table which has a 1:1 relationship between all Portfolio tables.
Hope this helps, otherwise let me know where I've misunderstood you.
Cheers,
Oscar
I have a table with large amount of records:
date instrument price
2019.03.07 X 1.1
2019.03.07 X 1.0
2019.03.07 X 1.2
...
When I query for the day opening price, I use:
1 sublist select from prices where date = 2019.03.07, instrument = `X
It takes a long time to execute because it selects all the prices on that day and get the first one.
I also tried:
select from prices where date = 2019.03.07, instrument = `X, i = 0 //It does not return any record (why?)
select from prices where date = 2019.03.07, instrument = `X, i = first i //Seem to work. Does it?
In Oracle an equivalent will be:
select * from prices where date = to_date(...) and instrument = "X" and rownum = 1
and Oracle will stop immediately when it finds the first record.
How to do this in KDB (e.g. stop immediately after it finds the first record)?
In kdb, where subclauses in select statements are executed sequentially. i.e. only those records which pass the first "test" get passed to the second test. With that in mind, looking at your two attempts:
select from prices where date = 2019.03.07, instrument = `X, i = 0 //It does not return any record (why?)
This doesn't (necessarily) return anything, because by the time it gets to the i=0 check, you've already filtered out some records (possibly including the first record in the original table, which would have i=0)
select from prices where date = 2019.03.07, instrument = `X, i = first i //Seem to work. Does it?
This one should work. First you filter by date. Then within the records for that date, you select the records for instrument `X. Then within those records, you take the record where i is the first i (where i has already been filtered down, so first i is simply the index of the first record [still the index from the original table, not the filtered down version])
Q-SQL equivalent for that is select[n] which also performs better than other approaches in most of the cases. Positive 'n' will give first n records and negative will give last n records.
q) select[1] from prices where date = 2019.03.07, instrument = `X
There is no inbuilt functionality to stop after first match. You can write custom function for that but that would probably execute slower than above supported version.
I have a portal on my "Clients" table. The related table contains the results of surveys that are updated over time. For each combination of client and category (a field in the related table), I only want the portal to display the most recently collected row.
Here is a link to a trivial example that illustrates the issue I'm trying to address. I have two tables in this example (Related on ClientID):
Clients
Table 1 Get Summary Method
The Table 1 Get Summary Method table looks like this:
Where:
MaxDate is a summary field = Maximum of Date
MaxDateGroup is a calculated field = GetSummary ( MaxDate ;
ClientIDCategory )
ShowInPortal = If ( Date = MaxDateGroup ; 1 ; 0 )
The table is sorted on ClientIDCategory
Issue 1 that I'm stumped on: .
ShowInPortal should equal 1 in row 3 (PKTable01 = 5), row 4 (PKTable01 = 6), and row 6 (PKTable01 = 4) in the table above. I'm not sure why FM is interpreting 1Red and 1Blue as the same category, or perhaps I'm just misunderstanding what the GetSummary function does.
The Clients table looks like this:
Where:
The portal records are sorted on ClientIDCategory
Issue 2 that I'm stumped on:
I only want rows with a ShowInPortal value equal to 1 should appear in the portal. I tried creating a portal filter with the following formula: Table 1 Get Summary Method::ShowInPortal = 1. However, using that filter removes all row from the portal.
Any help is greatly appreciated.
One solution is to use ExecuteSQL to grab the Max Date. This removes the need for Summary functions and sorts, and works as expected. Propose to return it as number to avoid any issues with date formats.
GetAsTimestamp (
ExecuteSQL (
"SELECT DISTINCT COALESCE(MaxDate,'')
FROM Survey
WHERE ClientIDCategory = ? "
; "" ; "";ClientIDCategory )
)
Also, you need to change the ShowInPortal field to an unstored calc field with:
If ( GetAsNumber(Date) = MaxDateGroupSQL ; 1 ; 0 )
Then filter the portal on this field.
I can send you the sample file if you want.
id datetime new_column datetime_rankx
1 12.01.2015 18:10:10 12.01.2015 18:10:10 1
2 03.12.2014 14:44:57 03.12.2014 14:44:57 1
2 21.11.2015 11:11:11 03.12.2014 14:44:57 2
3 01.01.2011 12:12:12 01.01.2011 12:12:12 1
3 02.02.2012 13:13:13 01.01.2011 12:12:12 2
3 03.03.2013 14:14:14 01.01.2011 12:12:12 3
I want to make new column, which will have minimum datetime value for each row in group by id.
How could I do it in Power BI desktop using DAX query?
Use this expression:
NewColumn =
CALCULATE(
MIN(
Table[datetime]),
FILTER(Table,Table[id]=EARLIER(Table[id])
)
)
In Power BI using a table with your data it will produce this:
UPDATE: Explanation and EARLIER function usage.
Basically, EARLIER function will give you access to values of different row context.
When you use CALCULATE function it creates a row context of the whole table, theoretically it iterates over every table row. The same happens when you use FILTER function it will iterate on the whole table and evaluate every row against the filter condition.
So far we have two row contexts, the row context created by CALCULATE and the row context created by FILTER. Note FILTER use the EARLIER to get access to the CALCULATE's row context. Having said that, in our case for every row in the outer (CALCULATE's row context) the FILTER returns a set of rows that correspond to the current id in the outer context.
If you have a programming background it could give you some sense. It is similar to a nested loop.
Hope this Python code points the main idea behind this:
outer_context = ['row1','row2','row3','row4']
inner_context = ['row1','row2','row3','row4']
for outer_row in outer_context:
for inner_row in inner_context:
if inner_row == outer_row: #this line is what the FILTER and EARLIER do
#Calculate the min datetime using the filtered rows
...
...
UPDATE 2: Adding a ranking column.
To get the desired rank you can use this expression:
RankColumn =
RANKX(
CALCULATETABLE(Table,ALLEXCEPT(Table,Table[id]))
,Table[datetime]
,Hoja1[datetime]
,1
)
This is the table with the rank column:
Let me know if this helps.
I have a dataset for each record it has a CompanyID, RevenueMonth, RevenueYear, Revenue
When I create the report, I am grouping each CompanyID and showing their monthly revenue for a given year.
But in a given year, not all companies have any revenues for a particular month.
Example:
A sample record would look like:
CompanyID, RevenueMonth, RevenueYear, Revenue
1,05,2013,5.00
1,08,2013,6.00
1,03,2013,3.00
End Result, I would like my report to look like this with CompanyID 1.
Company ID|01|02|03|04|05|06|07|08|09|10|11|12
1 0.00|0.00|3.00|0.00|5.00|0.00|0.00|6.00|0.00|0.00|0.00|0.00
In my current Report, it will only fill column headings with March (03), May (05) and August (08).
Company ID|03|05|08
1 3.00|5.00|6.00
How do I get my Report to add the missing months for the year?
I hope my questions is clear.
Database level
Since you're only returning a year at a time, you can create a calendar table and add this to your result set:
Keeping it as simple as possible, with the date table coming from a CTE:
with months as -- get required year/months
(
select RevenueYear = 2013
, RevenueMonth = 1
union all
select RevenueYear = 2013
, RevenueMonth = RevenueMonth + 1
from months
where RevenueMonth < 12
)
select CompanyID = coalesce(r.CompanyID, c.companyID)
, RevenueMonth = coalesce(r.RevenueMonth, m.RevenueMonth)
, RevenueYear = coalesce(r.RevenueYear, m.RevenueYear)
, Revenue = isnull(r.Revenue, 0.0)
from months m
cross join (select distinct CompanyID from records) c -- make sure all companies included
left join records r on m.RevenueYear = r.RevenueYear
and m.RevenueMonth = r.RevenueMonth
SQL Fiddle with demo.
This will return a year/month for each company in the result set.
In the long run it would be better to move from a CTE to a permanent calendar table in the database.
You can then implement this in the report using a matrix style tablix.
Report level
If you'd prefer to do this at the report level, you can set up a table-style tablix with 12 permanent columns, one for each month, then populate the month revenue cells with expressions like:
=Sum(IIf(Fields!RevenueMonth.Value = 2, Fields!Revenue.Value, Nothing)
For the February column.
This would work with your existing dataset without any database code changes.