Power BI DAX - Throughput Board Time Intelligence Metrics with different time zones - datetime

Dealing with a bit of a head scratcher. This is more of a logic based issue rather than actual Power BI code. Hoping someone can help out! Here's the scenario:
Site
Shift Num
Start Time
End Time
Daily Output
A
1
8:00AM
4:00PM
10000
B
1
7:00AM
3:00PM
12000
B
2
4:00PM
2:00AM
7000
C
1
6:00AM
2:00PM
5000
This table contains the sites as well as their respective shift times. The master table above is part of an effort in order to capture throughput data from each of the following sites. This master table is connected to tables with a running log of output for each site and shift like so:
Site
Shift Number
Output
Timestamp
A
1
2500
9:45 AM
A
1
4200
11:15 AM
A
1
5600
12:37 PM
A
1
7500
2:15 PM
So there is a one-to-many relationship between the master table and these child throughput tables. The goal is to create use a gauge chart with the following metrics:
Value: Latest Throughput Value (Latest Output in Child Table)
Maximum Value: Throughput Target for the Day (Shift Target in Master Table)
Target Value: Time-dependent project target
i.e. if we are halfway through Site A's shift 1, we should be at 5000 units: (time passed in shift / total shift time) * shift output
if the shift is currently in non-working hours, then the target value = maximum value
Easy enough, but the problem we are facing is the target value erroring for shifts that cross into the next day (i.e. Site B's shift 2).
The shift times are stored as date-independent time values. Here's the code for the measure to get the target value:
Var CurrentTime = HOUR(UTCNOW()) * 60 + MINUTE(UTCNOW())
VAR ShiftStart = HOUR(MAX('mtb MasterTableUTC'[ShiftStartTimeUTC])) * 60 + MINUTE(MAX('mtb MasterTableUTC'[ShiftStartTimeUTC]))
VAR ShiftEnd = HOUR(MAX('mtb MasterTableUTC'[ShiftEndTimeUTC])) * 60 + MINUTE(MAX('mtb MasterTableUTC'[ShiftEndTimeUTC]))
VAR ShiftDiff = ShiftEnd - ShiftStart
Return
IF(CurrentTime > ShiftEnd || CurrentTime < ShiftStart, MAX('mtb MasterTableUTC'[OutputTarget]),
( (CurrentTime - ShiftStart) / ShiftDiff) * MAX('mtb MasterTableUTC'[OutputTarget]))
Basically, if the current time is outside the range of the shift, it should have the target value equal the total shift target, but if it is in the shift time, it calculates it as a ratio of time passed within the shift. This does not work with shifts that cross midnight as the shift end time value is technically earlier than the shift start time value. Any ideas on how to modify the measure to account for these shifts?

Related

I have a question about optimizing the shifts scheduling (supply) to fulfill the hourly demand as much as possible in R

I would like to create an automatic shift planning tool through R with optimizing the demand.
Given that I have demand by hourly basis. I need to assign shift based on the demand in order to meet the demand as much as possible. I currently have 6 shifts (will list below).
The objective:
to minimize the difference between total supply and total demand
to minimize the difference between supply and demand for each hour
Constraint:
shift constraint - each hour might have several shifts available to be assigned
max capacity - I have the cap of supply. the sum of total shift cant exceed the cap for each hour.
Example:
Hourly_Demand <- c(22,19,18,21,22,28,34,39,44,50,49,47,44,43,50,56,56,61,59,59,46,39,34,26)
Cap <- c(46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,)
Shift_available <-
24Hr shift(A) - c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
16Hr shift(B) - c(0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0)
16Hr shift(C) - c(0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0)
16Hr shift(D) - c(0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0)
16Hr shift(E) - c(0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
8Hr shift(F) - c(0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0)
8Hr shift(G) - c(0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0)
The Timeline for Shift_Available is like c(7am , 8am , 9am , 10am , .... , 23pm , 0am , 1am , ... , 5am , 6am) . And '1' means it is available at that specific hour and contribution for 1 supply.
For example, if I assign 1 x shift(A) , 1 x shift(B), then the supply at 7am will be 1 , the supply at 10am will be 2 with the demand is 21 based on the demand vector.
May I have your opinion on how to make this out. Many thanks and apologize if there is anything explained not that clear.

Select records having a time interval greater than a certain value in Teradata

I am stuck with a simple problem related to finding out which queries took more than usual to complete. My script is the following:
locking row for access
SELECT
username,
CollectTimeStamp,
((firstresptime - starttime ) HOUR TO second ) AS ElapsedTime,
((firstresptime - firststeptime ) HOUR TO second ) AS ExecutionTime,
CAST(((firstresptime - firststeptime) SECOND) AS INTEGER) AS ExecutionTimeInt,
(ElapsedTime - ExecutionTime) AS Delay,
-- other kpis here
FROM dbql_data.dbql_all
where username ='MyUser';
and dateofday> '2017-07-01'
and ExecutionTimeInt > 5
However, I get records having ExecutionTimeInt less than 5.
Question: how can I get the records having a timeinterval greater than a certain value?
Extra info:
select * from dbc.dbcinfo; returns
InfoKey InfoData
1 VERSION 15.10.04.10
2 RELEASE 15.10.04.02
3 LANGUAGE SUPPORT MODE Standard
The ExecutionTimeInt calculation is likely to fail with an Interval overflow as it's limited to 9999 seconds.
ElapsedTime is an Interval, the correct way to compare is:
WHERE ElapsedTime > interval '5' second
or
WHERE ElapsedTime > interval '1' minute

Automatically count DB records by interval and write result periodically to aggregation table

I have a SQLITE3 DB with following 3 column layout
typ (1=gas or 0=electrical power) | time (seconds since epoch) | value (float)
In there, I document events from a gas meter which fires every 10 liter of consumed gas. This is (when the gas heating is active) once every ~20 seconds. The value written together with the timestamp is 0 (zero).
I want to automatically fill an aggregaton table with the count of all records within an interval of 10 minutes.
I had success with this query to get the counts within the intervals:
select time/600*600+600 _time, count(*) _count
from data
where typ = 1 and value = 0
group by _time
order by _time
But how would I achive the following:
run this query regularely every 10 minutes (or at every INSERT with a TRIGGER?) at xx:10 / xx:20 / xx:20 / ...
write the resulting count of only the last 10 minutes to an aggregation table together with the interval end time.
I of course could do this with a program (e.g. PHP) but I'd prefer a DB-only solution if possible.
Thanks for any help.
This trigger will run for every inserted row, and tries to insert a corresponding row in an aggregate table if one does not already exist. Then it increments the counter value in the aggregate table for the timespan of the newly inserted row.
create trigger after insert on data
begin
insert or ignore into aggregateData(startTime, counter) values ((new.time / 600) * 600, 0);
update aggregateData set counter = counter + 1 where startTime = (new.time / 600) * 600;
end;
I think that I found an easier solution which in the end creates the same result:
Just turn my aggregate query into a view:
CREATE VIEW _aggregate as
select time/600*600+600 _time, count(*) _count
from data
where typ = 1 and value = 0
group by _time
order by _time
This gives me exactly my desired result if I do a:
select * from _aggregate
It's good enough to have the aggregated values at runtime and not to store them. Or do you see a substantial difference to your solution?

Calculate the max samples with ramp up

I got this math problem. I am trying to calculate the max amount of samples when the response time is zero. My test has 3 samples (HTTP Request). The total test wait time is 11 seconds. The test is run for 15 minutes and 25 seconds. The ramp up is 25 seconds, this means that for every second 2 users are created till we reach 50.
Normally you have to wait for the server to respond, but I am trying to calculate the max amount of samples (this means response time is zero.) How do i do this. I can't simply do ((15 * 60 + 25) / 11) * 50. Because of the ramp up.
Any ideas?
EDIT:
Maybe I should translate this problem into something generic and not specific to JMeter So consider this (maybe it will make sense to me aswel ;)).
50 people are walking laps around the park. Each lap takes exactly 11 seconds to run. We got 15 minutes and 25 seconds to walk as many as possible laps. We cannot start all at the sametime but we can start 2 every second (25seconds till we are all running). How many laps can we run?
What i end up doing was manually adding it all up...
Since it takes 25s to get up to full speed, only 2 people can walk for 900s and 2 people can walk for 901s and 2 people can walk for 902s all the way to total of 50 people..
Adding that number together should give me my number i think.
If I am doing something wrong or based on wrong conclusion I like to hear your opinion ;). Or if somebody can see a formula.
Thanks in advance
I have no idea about jmeter, but I do understand your question about people running round the park :-).
If you want an exact answer to that question which ignores partial laps round the park, you'll need to do (in C/java terminology) a for loop to work it out. This is because to ignore partial laps it's necessary to round down the number of possible laps, and there isn't a simple formula that's going to take the rounding down into account. Doing that in Excel, I calculate that 4012 complete laps are possible by the 50 people.
However, if you're happy to include partial laps, you just need to work out the total number of seconds available (taking account of the ramp up), then divide by the number of people starting each second, and finally divide by how many seconds it takes to run the lap. The total number of seconds available is an arithmetic progression.
To write down the formula that includes partial laps, some notation is needed:
T = Total number of seconds (i.e. 900, given that there are 15 minutes)
P = number of People (i.e. 50)
S = number of people who can start at the Same time (i.e. 2)
L = time in seconds for a Lap (i.e. 11)
Then the formula for the total number of laps, including partial laps is
Number of Laps = P * (2 * T - (P/S - 1)) / (2*L)
which in this case equals 4036.36.
Assume we're given:
T = total seconds = 925
W = walkers = 50
N = number of walkers that can start together = 2
S = stagger (seconds between starting groups) = 1
L = lap time = 11
G = number of starting groups = ceiling(W/N) = 25
Where all are positive, W and N are integers, and T >= S*(G-1) (i.e. all walkers have a chance to start). I am assuming the first group start walking at time 0, not S seconds later.
We can break up the time into the ramp period:
Ramp laps = summation(integer i, 0 <= i < G, N*S*(G-i-1)/L)
= N*S*G*(G-1)/(2*L)
and the steady state period (once all the walkers have started):
Steady state laps = W * (T - S*(G-1))/L
Adding these two together and simplifying a little, we get:
Laps = ( N*S*G*(G-1)/2 + W*(T-S*(G-1)) ) / L
This works out to be 4150 laps.
There is a closed form solution if you're only interested in full laps. If that's the case, just let me know.

Calculating duration when you have hours, minutes, seconds, and milliseconds

I am writing a program in Fortran and I need a way of calculating the duration of the program down to milliseconds. I have been using the function "date_and_time", which leaves me with an array containing the system's time in hours, minutes, seconds, and milliseconds.
I believe that I can call this function at the start of my program to store the current time, then call the function again at the end of my program to store the latest time. But after that, how would I computer the duration? I tried just subtracting the values, but the milliseconds reset when one second passes, just like the seconds reset when one minute passes. How would be best way to approach this be?
Here is the program:
PROGRAM TEST_TIME_AND_DATE
INTEGER I
REAL J
INTEGER TIME_A(8), TIME_B(8)
CALL DATE_AND_TIME(VALUES=TIME_A)
PRINT '(8I5))', TIME_A
DO I = 0, 400000000
J = I * I - J
END DO
CALL DATE_AND_TIME(VALUES=TIME_B)
print '(8I5))', TIME_B
END PROGRAM TEST_TIME_AND_DATE
And here is the result:
2011 6 11 -300 9 14 49 304
2011 6 11 -300 9 14 50 688
I'm not sure what to do here, thanks.
If you want elapsed clock time, it would be simpler to use the intrinsic procedure system_clock since it provides a single time-value output. (There are additional arguments to provide information about the procedure, which is why it is a procedure instead of a function.) See, for example, http://gcc.gnu.org/onlinedocs/gfortran/SYSTEM_005fCLOCK.html. If you want to time the CPU usage, then use cpu_time. For either, two calls, at the start and end of the program, then a simple difference. You can use the COUNT_RATE argument to convert to integer count of time into seconds.
You can subtract the numbers, then convert everything into milliseconds and sum up the ms, sec in ms, min in ms, hrs in ms, ...
In your case this would be
0 + 0 + 0 + 0 + 0 + 1*1000 + 384 = 1384 [ms]
This approach works fine also with overflows since a positive number in a left-more column outweights negative numbers if they are all converted to the same basis. E.g. 0:58.000 to 1:02.200 yields
1 * 60000 + (-56) * 1000 + 200 = 4200
Please note that this does work up to days but not with months since they do not share a common length.
You could calculate the offset from some starting time (Jan 1, 1970 for UNIX) in seconds or milliseconds. The difference in those numbers is your elapsed time.
(2011 - 1970) * (number of seconds in a year) +
(month of the year - 1) * (number of seconds in a month) +
(day of the month - 1) * (number of seconds in a day) +
( ... )

Resources