I want to extract the week as date range from a DATETIME field in bigquery.
From these docs I can extract the week as a week number like this
EXTRACT(WEEK FROM date), or get the first day as date like this DATE_TRUNC(DATE(date), WEEK)
But what if I want to get a date range, for example if the date field have the value 2021-12-23 04:30:00 and say Sunday is the first the of the week, I would like to get this result 2021-12-19 - 2021-12-25
or something similar. Is it possible?
Depending on your desired output, separate columns or single string, you can try the following:
with sample_data as (
SELECT date FROM UNNEST(generate_timestamp_array('2021-12-01 00:00:00', '2022-02-01 00:00:00', INTERVAL 1 DAY)) as date
)
select
date
, DATE_TRUNC(DATE(date), WEEK) week_start
, DATE_TRUNC(DATE(date), WEEK) +6 week_end
, LAST_DAY(DATE(date), WEEK) as alt_week_end
, concat(DATE_TRUNC(DATE(date), WEEK)," - ", DATE_TRUNC(DATE(date), WEEK) +6) week_range
from sample_data
Consider below approach
select *,
date_trunc(date(date), week) week_start,
last_day(date(date), week) week_end
from your_table
with output like
Related
So I've been trying to fetch some daily data with SYSDATE on a date type YYYYMMDD as following:
SELECT dates, trunc(calendar_date, 'DD') calendar_dates, weekday_nbr
FROM db.date
WHERE dates BETWEEN to_char(TRUNC(SYSDATE)-2, 'YYYYMMDD') AND to_char(TRUNC(SYSDATE)-1, 'YYYYMMDD')
But now I'm trying to use the same but on a YYYY+MM+Week date type with not much success
I tried using:
SELECT T time, period, fiscal_week
FROM db.time
WHERE time BETWEEN to_char(TRUNC(SYSDATE)-2, 'W') AND to_char(TRUNC(SYSDATE)-1,'W')
With time as a 7 digit number, and period and fiscal week as a 2 digit number
Knowing that there's no way I can truncate such date type, how can TRUNC SYSDATE YYYY+MM+Week to get the data on the last 2 weeks?
Also I was thinking about maybe getting the totals from a set day and then dropping all but the last 2 weeks, but on the long run maybe that would be time consuming.
Knowing that there's no way I can truncate such date type, how can TRUNC SYSDATE YYYY+MM+Week to get the data on the last 2 weeks?
Assuming that your fiscal weeks are from Monday-Sunday then you can truncate to the start of the ISO week (which is always Midnight on Monday) and use that for the basis of the comparison:
SELECT *
FROM db.time
WHERE dates >= TRUNC(SYSDATE, 'IW') - INTERVAL '14' DAY
AND dates < TRUNC(SYSDATE, 'IW')
If you have a column that is for weeks then you should still use a DATE data type and add a CHECK constraint (and can use virtual columns to generate the week and the year):
CREATE TABLE time (
dt DATE
CHECK (dt = TRUNC(dt, 'IW')),
year NUMBER(4,0)
GENERATED ALWAYS AS (EXTRACT(YEAR FROM dt)),
month NUMBER(2,0)
GENERATED ALWAYS AS (EXTRACT(MONTH FROM dt)),
week NUMBER(1,0)
GENERATED ALWAYS AS (FLOOR((dt - TRUNC(dt, 'MM'))/7) + 1),
time VARCHAR2(7)
GENERATED ALWAYS AS (
CAST(
TO_CHAR(dt, 'YYYYMM')
|| (FLOOR((dt - TRUNC(dt, 'MM'))/7) + 1)
AS VARCHAR2(7)
)
)
-- ...
);
fiddle
Then you can use the logic above on the date column.
If you do not have a DATE column then you will need to convert your YYYYMMW number into a DATE and then use the logic above.
For example, if the logic for your fiscal weeks (which you have not described) is that the first week of each month starts on the first Monday of the month then you can convert the YYYYMMW number to a DATE using:
SELECT NEXT_DAY(
TO_DATE(SUBSTR(time, 1, 6), 'YYYYMM') - INTERVAL '1' DAY,
'MONDAY'
) + INTERVAL '7' DAY * (SUBSTR(time, 7, 1) - 1) AS week_start
FROM db.time
and then could use it to filter the table using:
SELECT *
FROM (
SELECT t.*,
NEXT_DAY(
TO_DATE(SUBSTR(time, 1, 6), 'YYYYMM') - INTERVAL '1' DAY,
'MONDAY'
) + INTERVAL '7' DAY * (SUBSTR(time, 7, 1) - 1) AS week_start
FROM db.time t
)
WHERE week_start >= TRUNC(SYSDATE, 'IW') - INTERVAL '14' DAY
AND week_start < TRUNC(SYSDATE, 'IW')
If you have different logic for calculating when fiscal weeks start then you will need to apply that logic to the conversion.
I need to pull out first date and last date of the month from the given from_date and to_date as input, For Example:-
I have my psql output table as the following:
Year
Term
Start Date
End Date
2022
Odd
01-02-2022
30-04-2022
2022
Even
01-07-2022
30-09-2022
I need the output as the following:-
Year
Term
Start Date
End Date
2022
Odd
01-02-2022
28-02-2022
2022
Odd
01-03-2022
31-03-2022
2022
Odd
01-04-2022
30-04-2022
2022
Even
01-07-2022
30-07-2022
2022
Even
01-08-2022
31-08-2022
2022
Even
01-09-2022
30-09-2022
I need the ouput in Postgresql, Pls help
Thanks
Your issue boils down to given a period with start and end dates, determine the first and last dates for each month in that period. In Postgres given a date you can determine the first (with date_trunc function) and last of the a month with the expressions:
-- for a given date
date_trunc('month', given_date) -- returns first day of month
date_trunc('month', given_date + interval '1 month' - interval '1 day') -- returns last day of month
Use the first expression above, with generate_series with dates, to create the first of each month in the period. The use the second expression to generate the end of each month. (see demo)
with range_dates (year, term, gsom) as
( select year
, term
, generate_series( date_trunc('month', od.start_date)::date
, date_trunc('month', od.end_date )::date
, interval '1 month'
)::date
from output_data od
)
select year
, term
, gsom start_date
, (gsom + interval '1 month' - interval '1 day')::date end_date
from range_dates
order by term desc, start_date;
I am trying to find an easy way to exclude partial weeks from the results.
What I have so far:
WITH a AS (SELECT
FORMAT_DATE("%G-%V", created_date) as report_week
, created_date
, FORMAT_DATE('%A', created_date) AS day
, emp_id
, ROUND(SAFE_DIVIDE(SUM(working_time),3600),2) as hours
FROM `table1` a
WHERE created_date >= current_date()-10
GROUP BY 1,2,3,4,5)
SELECT
report_week
, emp_id
, hours
FROM a
WHERE day LIKE '%Monday%'
GROUP BY 1,2,3
ORDER BY report_week ASC
Input:
report_week: conversion of employee's shift date into week
created_date: date of employee's shift
day: conversion of date of employee's shift into day of week (Monday, Tuesday..)
emp_id: the employee's ID
hours: Number of worked hours by the employee
if current_date is 19 April 2022 then current_date()-10 is 9 April 2022.
Output:
The desired output is to return the number of hours worked for each employee during the full week 11 - 17 April only (it would exclude 9th, 10th, 18th and 19th of April from the results).
To obtain this, I tried to filter by having only week starting on a Monday with WHERE day LIKE '%Monday%' but in the example, it would also return the number of hours worked for each employee on 18th and 19th (since the 18th is a Monday). And if I combine this clause with AND (for example WHERE day LIKE '%Monday%' AND day LIKE '%Sunday%', it does not work at all.
Additionally, I see here another potential problem. If a Monday is a day off (like during Easter), then no employees will have hours on that Monday and the rest of the week will then not be returned.
My question: Is there an easy way to get only full weeks (Monday-Sunday) regardless the date range chosen?
Thank you in advance.
Best,
Fabien
You need to use UNNEST and create an array with a range of dates. Also, you need to use DATE_TRUNC to get the week and LAST_DAY to get the last day of the week. You can get the weeks that belong to each day in a range of dates.
You can see this example.
with sample_data as (
SELECT date FROM UNNEST(generate_timestamp_array('2022-04-09 00:00:00', '2022-04-19 00:00:00', INTERVAL 1 DAY)) as date
),
counting as(
select
DATE_ADD(DATE (date), INTERVAL 1 DAY) date
, DATE_TRUNC(DATE(date), WEEK)+1 week_start
, DATE_TRUNC(DATE(date), WEEK) +7 week_end
from sample_data
)
select b.date from (
select week_start,count(*) as ndays
from counting
group by week_start
having ndays=7
) a
join counting b on a.week_start=b.week_start
where timestamp(b.date) between timestamp(b.week_start) and timestamp(b.week_end)
I used the same range of dates like your example.
Suppose I have a query:
SELECT ga_channelGrouping, ga_sourceMedium, SUM(ga_sessionDuration)/SUM(ga_sessions) as avg_sessionDuration
FROM database.table
group by ga_channelGrouping, ga_sourceMedium
.
How do I select last week and this week's data from BigQuery if I have a DATE column which looks like this 2018-06-19 11:00:00 UTC.
DATE_TRUNC is a useful function to get the beginning of the week and DATE_SUB gets you to last week
DATE_TRUNC
DATE_SUB
SELECT if(date(date) >= DATE_TRUNC(current_date(), WEEK(MONDAY)),"This Week","Last Week") weekPeriod,
ga_channelGrouping,
ga_sourceMedium,
SUM(ga_sessionDuration)/SUM(ga_sessions) as avg_sessionDuration
FROM database.table
WHERE date(date) >= DATE_SUB(DATE_TRUNC(current_date(), WEEK(MONDAY)), INTERVAL 1 WEEK)
group by weekPeriod, ga_channelGrouping, ga_sourceMedium
If your week starts on a Sunday, simply change WEEK(MONDAY) to WEEK(SUNDAY)
I want to display all the data(count) between the given date range in week wise in oracle.
Select count(log.end_date)
from tablename
where log.end_date between '01-Jul-2013' AND '30-Jul-2013'
The date range can be between months also like - 01-Jun-2013 to 30-Jul-2013.
How can I display like this?
Count Week
23 wk1
45 wk2
67 wk3
34 wk4
78 wk5
and so on....
Thanks in advance
Have a look at this site and search for IW (ISO week)
You can alter your statement to be something like this:
SELECT count(log.end_date) Count,
to_char( date log.end_date, 'IW' ) Week
FROM tablename
WHERE log.end_date between '01-Jul-2013' AND '30-Jul-2013'
GROUP BY to_char( date log.end_date, 'IW' )
EDIT:
Did not take a part of the question into my query. Here is an updated version that substracts the ISO week of the first week and adds one to get wk1, wk2, wk3....
SELECT count(log.end_date) Count,
'wk' || (1 + to_char( date log.end_date, 'IW' ) - to_char( date '01-Jul-2013', 'IW')) Week
FROM tablename
WHERE log.end_date between '01-Jul-2013' AND '30-Jul-2013'
GROUP BY to_char( date log.end_date, 'IW' )
You are looking for to_char with either IW or WW format. You are also looking for the way to group by this week:
select count(*), to_char(end_date,'IW')
from tablename
where trunc(end_date) between to_date('01-07-2013','dd-mm-yyyy') and to_date('30-07-2013','dd-mm-yyyy')
group by to_char(end_date,'IW')
order by to_char(end_date,'IW');
From Oracle http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm:
IW Week of year (1-52 or 1-53) based on the ISO standard.
WW Week of year (1-53) where week 1 starts on the first day of the year and continues to the seventh day of the year.