Calculating hours based on dates for weekend/weekday/public holiday - date

I've been attempting to use networkdays.intl to calculate hours for a weekend/weekday and public holiday.
The calculation is correct except when the time starts in 1 day and ends in another day for a shift (IE: 9pm until 2am)
Formula used for weekday
=NETWORKDAYS.INTL(B2,D2,"0000011",$T$2:$T$7)*G2
Formula used for weekend
=NETWORKDAYS.INTL(B2,D2,"1111100",$T$2:$T$7)*G2
Formula used for public holiday (basic)
=SUM(I2-Q2-R2)
Example sheet with highlighted cells causing the miscalculation.
Calculating hours on dates
Appreciate any suggestions.

Q12:
=INDEX(TEXT(SUM(QUERY({TEXT(SEQUENCE(D12-B12+1, 1, B12), {"ddd", "#"}),
{1-C12; SEQUENCE((D12-B12+1)-2, 1, 1, ); E12}},
"select Col3
where not Col1 matches 'Sat|Sun'
and not Col2 matches '"&TEXTJOIN("|", 1, IFERROR(1/(1/T2:T)))&"'")*1), "[h]:mm:ss"))
R12:
=INDEX(TEXT(SUM(IFNA(QUERY({TEXT(SEQUENCE(D12-B12+1, 1, B12), {"ddd", "#"}),
{1-C12; SEQUENCE((D12-B12+1)-2, 1, 1, ); E12}},
"select Col3
where Col1 matches 'Sat|Sun'
and not Col2 matches '"&TEXTJOIN("|", 1, IFERROR(1/(1/T2:T)))&"'"))*1), "[h]:mm:ss"))
S12:
=INDEX(TEXT(SUM(IFNA(QUERY({TEXT(SEQUENCE(D12-B12+1, 1, B12), {"ddd", "#"}),
{1-C12; SEQUENCE((D12-B12+1)-2, 1, 1, ); E12}},
"select Col3
where Col2 matches '"&TEXTJOIN("|", 1, IFERROR(1/(1/T2:T)))&"'"))*1), "[h]:mm:ss"))

Related

Google Sheets, query, select by month

I'm trying to select data by month but the behavior of the query/select is not what I expect. Here's a simplified sheet:
The month column just uses month() on column A and produces what I'd expect 1, 2, 3, 4
But the query in column D behaves as if the months are numbered 0, 1, 2, 3
What am I doing wrong?
months in QUERY actually starts from 0 so your formula should be:
=QUERY(A:B, "select B where month(A)+1 = 1", )
or:
=QUERY(A:B, "select B where month(A) = 0", )
for getting January
documentation:

Second minimum date in power bi

I have some users with different game_id.
for each user, I want to find the second minimum date. (column: min2_date)
If a user doesn't have a second date (look at user_id: 2, in this example), his min2_date should be -1.
If the second minimum date is the same as the first minimum date(look at user_id: 4), we should write that date in the min2_date column.
I don't know How I should calculate the second minimum date in Power BI.
please help me if you know.
Because you dont want a real second min date (but date in second row by order), we must try some trickyway.
One of way that we can do that is:
MinDate2 =
var _countrows = CALCULATE(countrows(VALUES(games[dates])), ALL(games[dates]) )
return
if(_countrows = 1, -1,
FORMAT(DISTINCT(TOPN(1,TOPN(2,CALCULATETABLE(SELECTCOLUMNS(games, "dates",games[dates]), ALL(games[dates])),[dates], asc), [dates], desc)), "yyyy-mm-dd")
)
where MinDate and MinDate2 are measures.
AS a calculatedColumn:
MinDate2_col =
var _countrows = CALCULATE(countrows(VALUES(games[dates])), ALL(games[dates]) )
return
if(_countrows = 1, "-1",
FORMAT(DISTINCT(TOPN(1,TOPN(2,CALCULATETABLE(SELECTCOLUMNS(games, "dates",games[dates]), ALL(games[dates])),[dates], asc), [dates], desc)), "yyyy-mm-dd")
)

Find all instances of a date in a date range - SQL Server

I need to find the price for an item for each financial year end date in a date range. In this case the financial year is e.g. 31 March
The table I have for example:
ItemID
Value
DateFrom
DateTo
1
10
'2019/01/01'
'2021/02/28'
1
11
'2021/03/01'
'2021/05/01'
SQL Fiddle
The SQL would thus result in the above table to be:
ItemID
Value
DateFrom
DateTo
1
10
'2019/01/01'
'2019/03/30'
1
10
'2020/03/31'
'2021/02/28'
1
11
'2020/03/01'
'2021/03/30'
1
11
'2020/03/31'
'2021/05/01'
You can solve it, but a prerequisite is the creation of a table called financial_years and filling it with data. This would be the structure of the table:
financial_years(id, DateFrom, DateTo)
Now that you have this table, you can do something like this:
select ItemID, Value, financial_years.DateFrom, financial_years.DateTo
from items
join financial_years
on (items.DateFrom between financial_years.DateFrom and financial_years.DateTo) or
(items.DateTo between financial_years.DateFrom and financial_years.DateTo)
order by financial_years.DateFrom;
The accepted answer is not correct, as it does not split out different parts of the year which have different values.
You also do not need a Year table, although it can be beneficial. You can generate it on the fly using a VALUES table.
Note also a better way to check the intervals overlap, using AND not OR
WITH Years AS (
SELECT
YearStart = DATEFROMPARTS(v.yr, 3, 31),
YearEnd = DATEFROMPARTS(v.yr + 1, 3, 31)
FROM (VALUES
(2015),(2016),(2017),(2018),(2019),(2020),(2021),(2022),(2023),(2024),(2025),(2026),(2027),(2028),(2029),(2030),(2031),(2032),(2033),(2034),(2035),(2036),(2037),(2038),(2039)
) v(yr)
)
SELECT
i.ItemID,
i.Value,
DateFrom = CASE WHEN i.DateFrom > y.YearStart THEN i.DateFrom ELSE y.YearStart END,
DateTo = CASE WHEN i.DateTo > y.YearEnd THEN y.YearEnd ELSE i.DateTo END
FROM items i
JOIN Years y ON i.DateFrom <= y.YearEnd
AND i.DateTo >= y.YearStart;

Select if number range contains number in PostgreSQL

I need to be able to find a row based on a number range, saved as a text field. For example, the field tuesday looks like 540-1020. I want to retrieve this row if I search for 900. So far I have,
SELECT string_to_array(tuesday, '-')
FROM coverage
WHERE 900 IN string_to_array(tuesday, '-')
Where string_to_array(tuesday, '-') prints out like {540,1020}. How can I convert it into a selectable integer range?
Use a range.
SELECT string_to_array(tuesday, '-')
FROM coverage
WHERE 900 <# int4range(split_part(tuesday, '-', 1)::int4, split_part(tuesday, '-', 2)::int4, '[]');
That last parameter [] signifies an inclusive range where '100-900' would match. You could also do an exclusive upper range like [) (note the right paren) where '100-900' would not match because the upper number is excluded from the set of matching numbers.
For better query speed as your table gets larger, you can add a GIST functional index.
CREATE INDEX tuesday_range_idx ON coverage
USING GIST (int4range(split_part(tuesday, '-', 1)::int4, split_part(tuesday, '-', 2)::int4, '[]'));
This is exposing some weaknesses in your data model. By having each day as a column, you'd have to create a separate functional index for each column. You're also having to parse text into an array every time you run this. Typically you'd want the data in the table to match how you access it, not its serialized form.
Instead of
CREATE TABLE coverage (
id serial PRIMARY KEY,
year smallint, -- tracking by week
week_num smallint, -- for example
sunday varchar,
monday varchar,
tuesday varchar,
wednesday varchar,
thursday varchar,
friday varchar,
saturday varchar
);
why not something like
CREATE TABLE coverage (
id serial PRIMARY KEY,
day date NOT NULL UNIQUE,
daily_data int4range NOT NULL
);
INSERT INTO coverage (day, daily_data)
VALUES ('2020-06-02', '[540,1020]');
Then your search looks like
SELECT daily_data
FROM coverage
WHERE extract(DOW FROM day) = 2 -- Tuesday (Sunday is 0, Saturday is 6)
AND 900 <# daily_data;
You can make indexes for the daily data ranges, by date (already a unique index in my example), functional indexes for the day of the week, month, year, etc. Much more flexible.
Or if you absolutely want an array back from your SELECT
SELECT ARRAY[lower(daily_data), upper(daily_data)]
FROM coverage
WHERE extract(DOW FROM day) = 2 -- Tuesday (Sunday is 0, Saturday is 6)
AND 900 <# daily_data;

How to find the quarter,year,month,semester start and end dates

I have a date dimension set in the SSAS Cube. Below is the screenshot attached.
I have been trying get quarter,year,month,semester start and end dates using ClosingPeriod() and OpeningPeriod() functions but not getting the exact value. How the get correct dates for a given date.
Syntax ClosingPeriod( [ Level_Expression [ ,Member_Expression ] ] )
You have to add calendar members ON 1. Example
WITH MEMBER [Measures].[X] AS
(
ClosingPeriod (
[Time].[Year Quarter Month].[Year Name],
[Time].[Year Quarter Month].CurrentMember
),
[Measures].[A]
)
SELECT [Measures].[X] ON 0,
[Time].[Year Quarter Month].[Year Name].Members ON 1
FROM [ABC]
I have month sorted by month name instead of the month number. After correction following query is working fine.
SELECT
{
OpeningPeriod([Dim Time].[Calendar].[Date],[Dim Time].[Calendar].[Date].&[2014-08-18T00:00:00].Parent.Parent.Parent.Parent)
} ON 0,
{
[Measures].[Ending Market Value Base]
} ON 1
FROM [Cube]