Get hours from schedule - google-sheets-formula

How can I get the total working hours scheduled with this format?
Expected output should be 46.

Not the prettiest things, but here are two ways to tackle it
=ARRAYFORMULA(
SUM(
IFERROR(
INDEX(SPLIT(TRANSPOSE(A2:G2)," - ",FALSE,TRUE),0,2)-
INDEX(SPLIT(TRANSPOSE(A2:G2)," - ",FALSE,TRUE),0,1)))*
24)
or
=ARRAYFORMULA(
SUM(
IFERROR(
REGEXEXTRACT(A2:G2,"- (\d+:\d+)")-
REGEXEXTRACT(A2:G2,"^(\d+:\d+)")))*
24)
Either way, we extract the second values then subtract the first values from that, sum it, and multiply it by 24.
For overnight shifts, try this
=ARRAYFORMULA(
SUM(
IFERROR(
IF(
--REGEXEXTRACT(A2:G2,"- (\d+:\d+)")<(--REGEXEXTRACT(A2:G2,"^(\d+:\d+)")),
1+REGEXEXTRACT(A2:G2,"- (\d+:\d+)")-
REGEXEXTRACT(A2:G2,"^(\d+:\d+)"),
REGEXEXTRACT(A2:G2,"- (\d+:\d+)")-
REGEXEXTRACT(A2:G2,"^(\d+:\d+)")))*
24))
in [hh]:mm:ss
=ARRAYFORMULA(
TEXT(
SUM(
IFERROR(
IF(
--REGEXEXTRACT(A2:G2,"- (\d+:\d+)")<(--REGEXEXTRACT(A2:G2,"^(\d+:\d+)")),
1+REGEXEXTRACT(A2:G2,"- (\d+:\d+)")-
REGEXEXTRACT(A2:G2,"^(\d+:\d+)"),
REGEXEXTRACT(A2:G2,"- (\d+:\d+)")-
REGEXEXTRACT(A2:G2,"^(\d+:\d+)")))),
"[hh]:mm:ss"))

Related

Optimizing DAX Has X Amount or More in Time Frame

I am looking to speed up this calculation that takes a minute or two to load each time I add a different filter view on the page.
The base measure just calculates the total logins in a rolling 3 month which works as expected.
TotalLoginsIn90 =
CALCULATE (
SUM ( [Logins] ),
DATESINPERIOD ( 'Calendar'[Date], LASTDATE ( Logins[Date] ), -3, MONTH )
)
I am now looking to identify in each month the amount of users that make over 3 logins in each month.
CustLoginIn90 =
CALCULATE (
SUMX ( DISTINCT ( Logins[Customer Number)] ), 1 ),
FILTER (
VALUES ( Logins[Cust Customer Number (Numeric)] ),
[TotalLoginsIn90] > 3
)
)
or
CustLoginIn90 =
CALCULATE (
DISTINCT ( Logins[Customer Number] ),
FILTER (
VALUES ( Logins[Cust Customer Number (Numeric)] ),
[TotalLoginsIn90] > 3
)
)
each of these takes its sweet time to calculate but ends up with the correct amount.
Is there any way to speed up these measures?
Thanks for the help!
I would recommend making the TotalLoginsIn90 as a calculated column instead of a measure so it only needs to be calculated once (per report refresh).
TotalLoginsIn90 =
CALCULATE (
SUM ( [Logins] ),
DATESINPERIOD (Logins[Date], Logins[Date], -3, MONTH)
)
That also allows you to write a very simple condition for your CustLoginIn90 measure:
CustLoginIn90 = SUMX(Logins, IF(Logins[TotalLogins90] > 3, 1, 0))

Dax sumifs .How to convert Excel formula to Dax formula

How to convert Excel formula to Dax formula. I want to find out sum qty of previous day hour 24 if the current hour is 1 .
Below is the example using excel formula.
=IF(E3=1,SUMIFS($F$3:$F$17,$C$3:$C$17,D3,$E$3:$E$17,24),0)
date,previous date,hour,qty,Formula
10/10/2016,10/09/2016,24, 5,0
10/11/2016,10/10/2016, 1, 1,8
10/12/2016,10/11/2016,24, 2,0
10/13/2016,10/12/2016,24, 2,0
10/13/2016,10/12/2016, 3, 2,0
10/14/2016,10/13/2016, 1, 2,32
10/14/2016,10/13/2016, 1, 2,32
10/14/2016,10/13/2016,24,10,0
10/14/2016,10/13/2016, 4,10,0
10/14/2016,10/13/2016,24,10,0
10/13/2016,10/12/2016,24,10,0
10/13/2016,10/12/2016, 1,10,2
10/13/2016,10/12/2016,24,10,0
10/13/2016,10/12/2016,24,10,0
10/10/2016,10/09/2016,24, 3,0
Let's say your table is called Table1.
Create a calculated column with this formula:
CALCULATE(SUM(Table1[qty]),FILTER(Table1,[date] = (EARLIER([date]) - 1) &&
Table1[hour]=24 && EARLIER([hour]) = 1))
This will replicate the results you were able to calculate using SUMIFS() in Excel.
Now, you can totally use this formula and run with it, but the slight caveat is that it returns blank instead of 0 for cases where the formula does not apply. In order to handle that, you can use a blank check in DAX, like so:
=var x =
CALCULATE(SUM([qty]),FILTER(Table1,[date] = (EARLIER([date]) - 1) && Table1[hour]=24
&& EARLIER([hour]) = 1))
RETURN IF(ISBLANK(x),0,x)
Here's a screen of the results, with the calculated column on the right:

Algorithm to find the most valuable combination?

I'm working on a small project where I need help in finding the best and cheapest tickets based on some input from the user:
Between what periods (start & end date)?
Within that period, are you skipping 1 or several dates?
How many times do you need to use the ticket each day?
There are x number of tickets. A ticket can cover:
Single ticket, to be used only once, price $5.
Period ticket (unlimited rides each day), to be used as much as you want from 1 day/$10, 3 days/$30, 7 days/$45..
I guess I'm looking for some kind of algorithm to determine the best combination of tickets based on periods (including or excluding skipping dates), and also their price.
Also, I guess there needs to be considered the case where it will be a better and cheaper outcome for me to buy a period ticket that covers more days than I actually need, but is cheaper based on how many rides I'm going for each day...
UPDATE (based on Petr suggestion..)
<?php
$tickets = array(
array("price"=>5, "label"=>"single", "period"=>null),
array("price"=>10, "label"=>"1 day", "period"=>1),
array("price"=>30, "label"=>"3 days", "period"=>3),
array("price"=>45, "label"=>"7 days", "period"=>7)
);
$trips = 2;
$startDate = new DateTime("2015-06-23");
$endDate = new DateTime("2015-06-30");
$endDate->modify("+1 day");
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($startDate, $interval, $endDate);
$cost = array();
$day = 1;
foreach( $period as $date ){
$span = $startDate->diff($date);
$days = ( $span->format('%a') + 1 );
$ticket = getCheapestTicket( $days );
$cost[ $day ] = $ticket;
$day++;
}
function getCheapestTicket( $days ){
global $tickets, $trips;
$lowestSum = null;
$cheapestTicket = null;
echo "-- getCheapestTicket --" . PHP_EOL;
echo "DAYS TO COVER: " . $days . " / TRIPS: " . $trips . PHP_EOL;
foreach( $tickets as $ticket ){
$price = $ticket['price'];
$period = $ticket['period'] ? $ticket['period'] : -1;
if( $ticket['period'] ){
$units = ceil( $days / $period );
$sum = round( $units * $price );
}else{
$units = ceil( $days * $trips );
$sum = round( ( $days * $price ) * $trips );
}
if( $sum <= $lowestSum || !$lowestSum ){
if( $ticket['period'] > $cheapestTicket['period'] ){
$cheapestTicket = $ticket;
$lowestSum = $sum;
}else{
$lowestSum = $sum;
$cheapestTicket = $ticket;
}
}
echo "TICKET: " . $ticket['label'] . " / Units to cover days: " . $units . " / Sum: " . $sum . " / Period: " . $period . PHP_EOL;
}
echo "CHEAPEST TICKET: " . $cheapestTicket['label'] .
" / PRICE PER UNIT: " . $cheapestTicket['price'] . " / SUM: " . $lowestSum . PHP_EOL. PHP_EOL;
return $cheapestTicket;
}
I'm not sure if this is on the way yet :)
Lets assume you have all the data stored in some array of days and each day has the number of rides for that day written down.
Side note: I am going to relax the conditions of a ticket lasting 24 hours and just assume each periodical ticket is good for that date (i.e, not starting at 15:00 and lasting until 14:59 the next day). This could be fixed by looking at it as hourly time units instead of days.
Sub optimal solution:
Now lets assign to all the days the cost of buying one ride tickets for that day and then start iterating over the array and checking whether or not you could substitute some of them with a cheaper ticket. You finish when no changes are done. The problem here is you might miss the optimal solution. You might assign two 3-day tickets (days 1-3 and 7-9) where a 7-day ticket (2-8) and two 1-day tickets would be better.
Tree solution: (data in leafs)
The tree option would be to arrange it in a tree with each sub tree holding the best solution for that sub tree. Then, each subtree root could check if using a ticket "covering" only part of the subtree could be useful, when taking into account the values of the roots of the parts left out.
Maybe a rank tree would come in handy here.
You can solve this problem using a dynamic programming approach.
Firstly, for simplicity of the algorithm, let's for each l calculate the cheapest single ticket that can be used to cover l consecutive days. For your example this will be: 1 day $10, 2 days $30 (buy a 3-day ticket and use it only for 2 days), 3 days $30, 4-7 days $45, etc. (There will obviously be some maximal value of l beyond which there will be no such ticket.) Denote these results as cost[l].
Now the main dynamic programming solution. For each date i in your [begin, end] range, calculate ans[i] = the minimal cost to buy tickets to cover at least interval from begin to i.
Assuming that you have already calculated all the values before date i, calculation for date i is simple. You will need some ticket that ends on day i. Let's say it covers length of l days, then the price for this last ticket will be cost[l], and you will also have to cover the days from begin to i-l, which will cost ans[i-l] (or zero if i-l is before begin). So for a given i iterate over all possible ls and find the one that minimizes the solution.
This gives you the O(NL) solution, where N is the number of days and L is the maximal span of a single ticket.
This all assumes that each ticked covers several full consecutive days. If it covers, say, 24 full hours (from the hour of buying to the same hour next day), then just calculate answers for each hour.
As from my example, based on what #Petr said, I don't really know how it can solve the situation where for example the period covers 8 days (2 trips each day) and you end up with a result like this:
-- getCheapestTicket --
DAYS TO COVER: 8 / TRIPS: 2
TICKET: single / Units to cover days: 16 / Sum: 80 / Period: -1
TICKET: 1 day / Units to cover days: 8 / Sum: 80 / Period: 1
TICKET: 3 days / Units to cover days: 3 / Sum: 90 / Period: 3
TICKET: 7 days / Units to cover days: 2 / Sum: 90 / Period: 7
CHEAPEST TICKET: 1 day / PRICE PER UNIT: 10 / SUM: 80
Where it should give me a result of this combination:
7 days, $45
1 day, $10
Or is this what you mean when you said "(There will obviously be some maximal value of l beyond which there will be no such ticket.)"?
Would be really sweet to get another round of explanation on your thoughts!

What time system is this?

Im trying to understand some program that handles time in a certain system I am still to know of. Hopefully you can tell me what system is, if any.
One of the value in numbers is 170000000 and it represents the 26th of April 2037. Another example is 164632577 which represents the 20th of December 2022.
I tested both with an EPOCH converter but I get completely different dates so its not EPOCH for sure. Have any clue?
Thank you.
We assume that the fomula for converting from a date to those strange time units is of the following form:
f(x) = m*x + b
where x is in strange time units and f is in days:
f(2037*365.2425 + 31 + 28 + 31 + 26) = 170000000
f(2022*365.2425 + 365.2425 - (31 + 1 - 20) = 164632577
because we have two data points, we can make two formulas:
I : f1 = m * x1 + b
II: f2 = m * x2 + b
Now we’re looking for: m, b
We solve as follows:
I => III: b = f1 - m*x1
III into II: f2 = m*x2 + f1 - m*x1 => f2 - f1 = m(x2 - x1) => m = (f2 - f1) / (x2 - x1)
goes down to:
m = 1024.04 units/day and (exactly 1024, most likely, because that’s 2^10)
with b = f1 - m*x1
b = -591973731.84 (??)
so you get:
for converting from days since year 1 to those strange time units:
f(x) = 1024 * x - 591973731.84
where x is in days, so year * 365.2524 + (months-1) * 30 + days
testing it reveals that
f(Jan 1st 2038 = 2038*365.2425) = 1024*2038*365.2425 - 591973731.84 = 170255224.3, which is just a bit more than Dec 20th 2037, so it works.
Strangely, the 0 point of those strange time units represents about the year 1582 (solution for x of f(x) = 0).
170000000 seems very rounded. Do you know exact seconds within the game your numbers represent?
It should be a linear system, and you know that the value of (170000000 - 164632577) = 5367423 equals the difference between your days (2037-04-26 - 2022-12-20) = 5241 days.
This means that one day is (5241 / 5367423) = 0.00097644623873...
Counting back from 164632577 to zero places takes us back (164632577 * 0.00097644623873...) = 160754.86 days, from 2022-12-20 to 1582-11-02.
Same calculations done on 170000000 takes us back (170000000 * 0.00097644623873...) = 165995,86 days, from 2037-04-26 to 1582-11-02. Heuruka!
So, you have a system where timeFor($value) = [1582-11-02] + [0.00097644623873... * $value days].
Issues:
There are several rounding issues with these numbers. Your dates most probably include seconds, but we've calculating on whole days.
We're moving back in time, and time travel related issues will appear. These include, but are not limited to, non existing dates according to your calendar.
Things to consider; October 15th of 1582, or 1582-10-15 is the start of the Gregorian calender. This is probably the real start date for your data.
Edit: I previously wrote that the multiplier should probably be 0.001, but as Daniel noted in another answer, it's actually 1/1024 = 0.0009765625.

Nested IIF or SWITCH Statement syntax needed correctly

Can somebody please tell me what I am missing in this formula in SSRS? Or better yet can somebody please write this same thing in a NESTED IIF syntax?
Switch(
(Parameters!StartMonth.Value <= 1 And Parameters!EndMonth.Value >= 1),
(Code.CalculateFraction(
(Fields!retail1.Value -Fields!cost1.Value) , Fields!cost1.Value
) *100
),
(Parameters!StartMonth.Value <= 2 And Parameters!EndMonth.Value >= 2),
(Code.CalculateFraction(
(
(Fields!retail1.Value +Fields!retail2.Value)-
(Fields!cost1.Value + Fields!cost2.Value)
) ,
(Fields!cost1.Value + Fields!cost2.Value)
) *100
)
)
This is seriously driving me crazy. For simplicity I have just put 2 iterations here. I have 12 of these and every next step I have to sum up retail1 until retail12 and cost1 until cost12.
I cant get it right for these two in the first place.
EDIT:
I am trying this now and still returns the value in the first condition
=iif(
Parameters!StartMonth.Value <= 1 AND Parameters!EndMonth.Value >= 1,
ReportItems!txtTotal2.Value,
iif(
Parameters!StartMonth.Value <= 2 AND Parameters!EndMonth.Value >= 2,
ReportItems!txtTotal3.Value,
iif(
Parameters!StartMonth.Value <= 3 AND Parameters!EndMonth.Value >= 3,
ReportItems!txtTotal4.Value,
Nothing
)
)
)
EDIT 2:
FIGURED OUT WHAT WAS INCORRECT.
My entire logic was incorrect to get to the result that I was expecting. It was obvious in my case that whatever I use, be it IIF or switch only the first statement would execute because it was true.
But I had to change the logic to get to the result that I wanted.
iif(
Parameters!EndMonth.Value = 1,
ReportItems!txtTotal1.Value,
Parameters!EndMonth.Value = 2,
ReportItems!txtTotal2.Value,
and so on
)
This solved my problem. Thanks guys I appreciate it.
Try using separated IIF Statements:
=iif(
Parameters!StartMonth.Value <= 1 AND Parameters!EndMonth.Value >= 1,
ReportItems!txtTotal2.Value, Nothing
) OR
iif(
Parameters!StartMonth.Value <= 2 AND Parameters!EndMonth.Value >= 2,
ReportItems!txtTotal3.Value, Nothing
) OR
iif(
Parameters!StartMonth.Value <= 3 AND Parameters!EndMonth.Value >= 3,
ReportItems!txtTotal4.Value, Nothing
)
Syntax looks correct at first glance. Most places in SSRS you are required to have = to start your statement. Your code above refers to embedded code for CalculateFraction() Does that exist and is it used successfully elsewhere?

Resources