Google sheets find MIN time of min price - sorting

Given the following data:
123 2020-06-22 23:00:00
124 2020-06-22 23:30:00
121 2020-06-23 00:00:00
I want the hour/minute of the minimum price in a Google Sheet. I tried using without success:
=QUERY(A:B,"select hour(B), min(A) group by todate(B)")
=QUERY(A:B,"select B, min(A) group by todate(B)")

try like this:
=INDEX(SORT(A:B); 1)
or for each date:
=ARRAY_CONSTRAIN(SORTN(SORT({A:B, DATEVALUE(B:B)}), 9^9, 2, 3, 1), 9^9, 2)

Related

DAX - How to sum a measure over the last N weeks, this year and last year

I have a measure [Total] reported by a custom week-ending date field 'Date'[CustWEndingDate] from Date table, based on Sat - Fri weeks (so each week ends on a Fri), plus an associated 'Date'[WeekNum] and 'Date'[Year] to that. Data looks like this:
[CustWEndingDate], [Year], [WeekNum], [Total]
3/29/2019, 2019, 13, 400
4/5/2019, 2019, 14, 350
4/12/2019, 2019, 15, 420
4/19/2019, 2019, 16, 390
...
3/27/2020, 2020, 13, 315
4/3/2020, 2020, 14, 325
4/10/2020, 2020, 15, 405
4/17/2020, 2020, 16, 375
My question is this: How do I create DAX measure to calculate last 3 weeks this year OVER same last 3 weeks last year? For example, week 14, 15 and 16 this year (325+405+375) vs same week 14, 15 and 16 last year (350+420+390)?
Thank you in advance for any help you can provide!
I would use the following approach:
Calculate scalar with today's date
Calculate scalar with year of today's date
Calculate scalar with WeekNum associated to today's date
Calculate scalar with CY value for last 3 weeks this year
Calculate scalar with PY value for (same) last 3 weeks previous year
Calculate ratio
Here is the technical implementation:
Joel's Measure:=
VAR _TODAY = TODAY()
VAR _YEAR = YEAR(_TODAY)
VAR _WEEKNUM = CALCULATE(MIN('Date'[WeekNum]), 'Date'[Date] = _TODAY)
VAR _CY = CALCULATE([MEASURE], 'Date'[Year] = _YEAR, 'Date'[WeekNum] IN {_WEEKNUM, _WEEKNUM - 1, _WEEKNUM - 2})
VAR _PY = CALCULATE([MEASURE], 'Date'[Year] = _YEAR - 1, 'Date'[WeekNum] IN {_WEEKNUM, _WEEKNUM - 1, _WEEKNUM - 2})
RETURN
DIVIDE(_CY - _PY, ABS(_PY))
This should solve your problem. If not, please share a feedback with the result.

Sum values by date range in multiple columns

I need to sum value by date range in multiple columns. Every date range is one week of a month. It can be shorter than 7 days if it is the start of the month or the end of the month.
For example, I have dates for February:
my_user my_date my_value
A 01.02.2019 100
A 02.02.2019 150
B 01.02.2019 90
Z 28.02.2019 120
How can I have in date range format such as below?
my_user 01/02-03/02 04/02-10/02 11/02-17/02 18/02-24/02 25/02-28/02
A 250 0 0 0 0
B 90 0 0 0 0
Z 0 0 0 0 120
Any suggestions? Thanks!
You can do this:
select *
from (
select to_char(dt, 'iw') - to_char(trunc(dt, 'month'), 'iw') + 1 wk, usr, val from t)
pivot (sum(val) for wk in (1, 2, 3, 4, 5, 6))
demo
USR 1 2 3 4 5 6
--- ---------- ---------- ---------- ---------- ---------- ----------
A 250
B 90
Z 120
Header numbers are the weeks of month. Maximum may be 6 if month starts at the end of the week and is longer than 28 days.
Similiar way you can find first and last day of each week if needed, but you can't put them as headers, or at least not easily.
Edit:
it is possible to define certain date range with pivot, simple as two
dates? For example, I need to sum values from 5 December 2018 to 4
January 2019, 5 January 2019 to 4 February 2019, 5 March 2019 to 4
April 2019
Yes. Everything depends on how we count first and next weeks. Here:
to_char(dt, 'iw') - to_char(trunc(dt, 'month'), 'iw') + 1
i am subtracting week in year for given date and week in year of first day in month for this date. You can simply replace this second value with your starting date, either by hardcoding it in your query or by sending parameter to query or finding minimum date at first in a subquery:
(to_char(dt, 'iw') - to_char(date '2019-03-05', 'iw')) + 1
or
(to_char(dt, 'iw') - to_char((select min(dt) from data), 'iw')) + 1
Edit 2:
There is one problem however. When user defined period contains two or more years. to_date(..., 'iw') works fine for one year, but for two we get values 51, 52, 01, 02... We have to deal with this somehow, for instance like here:
with t(dt1, dt2) as (select date '2018-12-16', date '2019-01-15' from dual)
select min(dt) mnd, max(dt) mxd, iw, row_number() over (order by min(dt)) rn
from (select dt1 + level - 1 dt, to_char(dt1 + level - 1, 'iw') iw
from t connect by level -1 <= dt2 - dt1)
group by iw
which gives us:
MND MXD IW RN
----------- ----------- -- ----------
2018-12-16 2018-12-16 50 1
2018-12-17 2018-12-23 51 2
2018-12-24 2018-12-30 52 3
2018-12-31 2019-01-06 01 4
2019-01-07 2019-01-13 02 5
2019-01-14 2019-01-15 03 6
In first line we have user defined date ranges. Then I did hierarchical query looping through all dates in range assigning week, then grouped by this week, found start and end dates for each week and assigned row number rn which can be further used by pivot.
You can now simply join your input data with this query, let's name it weeks:
from data join weeks on dt between mnd and mxd
and make pivot. But for longer periods you have to find how many weeks there can be and specify them in pivot clause in (1, 2, 3, 4...). You can also add aliases if you need:
pivot ... for rn in (1 week01, 2 week02... 12 week12)
There is no simply way to avoid listing them manually. If you need it please look for oracle dynamic pivot in SO, there where hundreds similiar questions already. ;-)

Finding cummulative sum of MAX values

I need to calculate the cumulative sum of Max value per period (or per category). See the embedded image.
So, first, I need to find max value for each category/month per year. Then I want to calculate the cumulative SUM of these max values. I tried it by setting up max measure (which works fine for the first step - finding max per category/month for a given year) but then I fail at finding a solution to finding cumulative SUM (finding the cumulative Max is easy, but it is not what I'm looking for).
Table1
Year Month MonthlyValue MaxPerYear
2016 Jan 10 15
2016 Feb 15 15
2016 Mar 12 15
2017 Jan 22 22
2017 Feb 19 22
2017 Mar 12 22
2018 Jan 5 17
2018 Feb 16 17
2018 Mar 17 17
Desired Output
Year CumSum
2016 15
2017 37
2018 54
This is a bit similar to this question and this question and this question as far as subtotaling, but also includes a cumulative component as well.
You can do this in two steps. First, calculate a table that gives the max for each year and then use a cumulative total pattern.
CumSum =
VAR Summary =
SUMMARIZE(
ALLSELECTED(Table1),
Table1[Year],
"Max",
MAX(Table1[MonthlyValue])
)
RETURN
SUMX(
FILTER(
Summary,
Table1[Year] <= MAX(Table1[Year])
),
[Max]
)
Here's the output:
If you expand to the month level, then it looks like this:
Note that if you only need the subtotal to work leaving each row as a max (15, 22, 17, 54) rather than as a cumulative sum of maxes (15, 37, 54, 54), then you can use a simpler approach:
MaxSum =
SUMX(
VALUES( Table1[Year] ),
CALCULATE( MAX( Table1[MonthlyValue] ) )
)
This calculates the max for each year separately and then adds them together.
External References:
Subtotals and Grand Totals That Add Up “Correctly”
Cumulative Total - DAX Patterns

Summing by Column

Suppose we have the following columns:
X Y Z
Category Date Amount
A January 10
A February 20
A March 30
B January 34
B February 45
B March 65
C January 87
C February 98
C March 100
D January 80
D February 90
I want to sum the Amount column by Category and Date . So for Category A, we would have the sum of the amount be 10+20+30 = 60 for the dates between January and March. In Oracle BI, how would we do this? Note that Some categories might have missing dates. So I want to sum the Amounts for the only the the available dates between January and March. Category D, for example, has March missing. So the total amount would be 80+90 = 170.
When I do the following, I just get the sum of all the amounts:
sum("Z"."Amount")
If the required result has to be achieved through OBIEE Answer, then it can be done in following way.
Create a table with columns - Category, Date, Amount.
Go to Results tab. Edit view of the table.
Click on Total By icon above Category column. Both After and Report-Based Total (when applicable) should be ticked.
The result will be coming as shown.
Category Date Amount
A January 10
February 20
March 30
A Total 60
B January 34
February 45
March 65
B Total 144
C January 87
February 98
March 100
C Total 285
D January 80
February 90
D Total 170
You can do this quite simply by editing the column formula from within the Criteria. When you look at it to begin, your Amount column formula probably looks something like "Z"."Amount". You can edit this slightly to change the aggregation level:
sum("Z"."Amount" by "X"."Category")
That should give you something like:
Category Date Amount
A Jan 60
A Feb 60
A Mar 60
B Jan 144
B Feb 144
B Mar 144

Algorithm to find nth working day [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have deviced a procedure to find nth working day without using loops.
Please bring around your suggesstions over this -
Algorithm to manipulate working days -
Problem: Find the date of nth working day from any particular day.
Solution:
Normalize to closest Monday -
If today(or the initial day) happens to be something other than monday, bring the day to the closest monday by simple addition or subtraction.
eg: Initial Day - 17, Oct. This happens to be wednesday. So normalize this no monday by going 2 dates down.
Now name this 2 dates, the initial normalization factor.
Add the number of working days + week ends that fall in these weeks.
eg: to add 10 working days, we need to add 12 days. Since 10 days has 1 week that includes only 1 saturday and 1 sunday.
this is because, we are normalizing to nearest monday.
Amortizing back -
Now from the end date add the initial normalization factor (for negative initial normalization) and another constant factor (say, k).
Or add 1 if the initial normalization is obtained from a Friday, which happens to be +3.
If start date falls on Saturday and sunday , treat as monday. so no amortization required at this step.
eg: Say if initial normalization is from wednesday, the intial normalization factor is -2. Hence add 2 to the end date and a constant k.
The constant k is either 2 or 0.
Constant definition -
If initial normalization factor is -3, then add 2 to the resulting date if the day before amortization is (wed,thu,fri)
If initial normalization factor is -2, then add 2 to the resulting date if the day before amortization is (thu,fri)
If initial normalization factor is -1, then add 2 to the resulting date if the day before amortization is (fri)
Example -
Find the 15th working day from Oct,17 (wednesday).
Step 1 -
initial normalization = -2
now start date is Oct,15 (monday).
Step 2 -
add 15 working days -
15 days => 2 weeks
weekends = 2 (2 sat, 2 sun)
so add 15 + 4 = 19 days to Oct, 15 monday.
end_date = 2, nov, Friday
Step 3a -
end_date = end_date + initial normalization = 4, nov sunday
Step 3b -
end_date = end_date + constant_factor = 4, nov, sunday + 2 = 6, nov (Tuesday)
Cross Verfication -
Add 15th working day to Oct, 17 wednesday
Oct,17 + 3 (Oct 17,18,19) + 5 (Oct 22-26) + 5 (Oct 29 - Nov 2) + 2 (Nov 5, Nov 6)
Now the answer is 6, Nov, Tuesday.
I have verified with a few cases. Please share your suggesstions.
Larsen.
To start with, its a nice algorithm, i have doubts about boundary conditions though: for example, what if i need to find the 0th working day from today's date:
Step 1 -
initial normalization = -2 now start date is Oct,15 (monday).
Step 2 -
add 0 working days -
0 days => 0 weeks
weekends = 0
so add 0 + 0 = 0 days to Oct, 15 monday.
end_date = 15, oct, monday
Step 3a -
end_date = end_date + initial normalization = 17, oct wednesday
Step 3b -
end_date = end_date + constant_factor = 17, Oct wednesday or 19,oct friday based on whether constant factor is 0 or 2 as it be only one of these values.
Now lets repeat the steps for finding the 1st working day from today:
Step 1 -
initial normalization = -2 now start date is Oct,15 (monday).
Step 2 -
add 1 working days -
1 days => 0 weeks
weekends = 0
so add 1 + 0 = 1 days to Oct, 15 monday.
end_date = 15, oct, monday
Step 3a -
end_date = end_date + initial normalization = 17, oct wednesday
Step 3b -
end_date = end_date + constant_factor = 17, Oct wednesday or 19,oct friday based on whether constant factor is 0 or 2 as it be only one of these values.
Did you notice, algorithm gives the same end result for 0 and 1. May be thats not an issue if t defined beforehand that 0 working days and 1 working days are considered as same scenario, but ideally they should be giving different results.
I would also suggest you to consider the negative test cases, like what if i need to find -6th working day from today, will your alforithm give me a date in past rightfully?
Lets consider 0th working day from today (17/10, wed).
Step 1 -
start_date = 17/10 wed
normalized date = 15/10 mon
Step 2 -
end_date = normalized date + working days
= 15/10 mon + 0 = 15/10 mon
Step 3 -
amortized_back = end_date_before_amortization + normalization factor
= 15/10 + (+2) = 17/10 wed
since the end_date_before_amortization falls on monday and initial normalization is 2, constant factor = 0.
hence, end_date = 17/10 wed.
now case 2, 1st working day from today.
Step 1 -
start_date = 17/10 wed
normalized date = 15/10 mon
Step 2 -
end_date = normalized date + working days
= 15/10 mon + 1 = 16/10 tue
Step 3 -
amortized_back = end_date_before_amortization + normalization factor
= 16/10 + (+2) = 18/10 thu.
since the end_date_before_amortization falls on tuesday and initial normalization is 2, constant factor = 0.
hence, end_date = 18/10 thu.
Looks to be working for 0th and 1st WD.

Resources