I have a query to select data and group by date(data year by years), I need to convert select data from standard week(monday to sunday) to israel week(which start from sunday and end on saturday)
my query:
select
data_date,
CONCAT(to_char(data_date::date, 'IYYY'), 'W', to_char(data_date::date, 'IW')) as standard_week,
CONCAT(to_char(data_date::date, 'IYYY'), 'W', floor(EXTRACT(doy FROM data_date::TIMESTAMP)/7 + 1)) as israel_week
from
data
where
data_date >= '2022-01-01'
and data_date <= '2022-01-31'
group by data_date, standard_week, israel_week
order by data_date
the result like this:
standard week looks ok but israel week was wrong, how can I make it correct?
Related
My financial year start from 01-Jul to 30-Jun every year.
I want to find out all financial year wise periods for a given date range.
Let's say, The date range is From_Date:16-Jun-2021 To_Date 31-Aug-2022. Then my output should be like
Start_Date, End_date
16-Jun-2021, 30-Jun-2021
01-Jul-2021, 30-Jun-2022
01-jul-2022, 31-Aug-2022
Please help me query. First record Start_Date must start from From_Date and Last record End_Date must end at To_Date
This should work for the current century.
with t(fys, fye) as
(
select (y + interval '6 months')::date,
(y + interval '1 year 6 months - 1 day')::date
from generate_series ('2000-01-01'::date, '2100-01-01', interval '1 year') y
),
periods (period_start, period_end) as
(
select
case when fys < '16-Jun-2021'::date then '16-Jun-2021'::date else fys end,
case when fye > '31-Aug-2022'::date then '31-Aug-2022'::date else fye end
from t
)
select * from periods where period_start < period_end;
period_start
period_end
2021-06-16
2021-06-30
2021-07-01
2022-06-30
2022-07-01
2022-08-31
Looks well as a parameterized query too with '16-Jun-2021' and '31-Aug-2022' replaced by parameter placeholders.
You want to create multiple records from one record (your date range). To accomplish this, you will need some kind of helper table.
In this example I created that helper table using GENERATE_SERIES and use it to join it to your date range, with some logic to get the dates you want.
dbfiddle
--Generate a range of fiscal years
WITH FISCAL_YEARS AS (
SELECT
CONCAT(SEQUENCE.YEAR, '-07-01')::DATE AS FISCAL_START,
CONCAT(SEQUENCE.YEAR + 1, '-06-30')::DATE AS FISCAL_END
FROM GENERATE_SERIES(2000, 2030) AS SEQUENCE (YEAR)
),
--Your date range
DATE_RANGE AS (
SELECT
'2021-06-16'::DATE AS RANGE_START,
'2022-08-31'::DATE AS RANGE_END
)
SELECT
--Case statement in case the range_start is later
--than the start of the fiscal year
CASE
WHEN RANGE_START > FISCAL_START
THEN RANGE_START
ELSE FISCAL_START
END AS START_DATE,
--Case statement in case the range_end is earlier
--than the end of the fiscal year
CASE
WHEN RANGE_END < FISCAL_END
THEN RANGE_END
ELSE FISCAL_END
END AS END_DATE
FROM FISCAL_YEARS
JOIN DATE_RANGE
--Join to get all relevant fiscal years
ON FISCAL_YEARS.FISCAL_START BETWEEN DATE_RANGE.RANGE_START AND DATE_RANGE.RANGE_END
OR FISCAL_YEARS.FISCAL_END BETWEEN DATE_RANGE.RANGE_START AND DATE_RANGE.RANGE_END
I want to define the start of a “month” as the 26th day of the previous calendar month (and of course ending on 25th).
How can I group by this definition of month using date_trunc()?
This expression gives the month you want:
date_trunc(
'month',
date_add(
day,
case
when extract(day from date) > 25 then 7
else 0
end),
my_date_col
)
)
Select it and group by it.
The logic is: If the day of the month is greater than 25, then add some days to bump it into the next month before truncating it to the month.
I would use an INTERVAL to calculate the correct dates. Here an example using generate_series():
SELECT d::date as reference_date
, (d + interval '25 days')::date AS first_day
, (d + interval '1 month' + interval '24 days')::date as last_day
FROM generate_series('2020-01-01'::timestamp, '2021-01-01'::timestamp, '1 month') g(d);
I hope someone can help with a calculation that I am having trouble developing.
I am developing a report in a DB2 database that I need to add "X" number of days to a "RECEIVED" date/time when an order comes in between X and Y; but exclude Weekends and Holidays to add to the received date. I have created a [TBLCALENDAR] that lists the Weekends and Holidays (Example below); and from this, I want to ADD X number of days to a "DUEDATE"
tblCalendar]
DATE DAYOFWK DAY HOLIDAY
1/19/2019 7 Saturday
1/20/2019 1 Sunday
1/21/2019 2 Monday YES
So, for example 1, if I have an order that is placed on 1/18/2019 at 4:01pm; the due date should be 1/23/2019 at 11:00am.
Example 2: if I have an order that is placed on 1/18/2019 at
Conditions are:
Previous Date 4:01pm to Current Date 11:00am = Due Date should be + "X" business days by 11:00am
If order received Current day by 4:00pm = Due Date should be + "X" business days by 4:00pm
I have tried to reference the tblCalendar to get the [Received] date/time and add X number of days based off of an order, but it's not functioning the way I have hoped.
I have used the following code...but it doesn't exclude Weekends or Holidays when adding the specified number of days or have my order time requirement to take into account previous day after 4:00pm to current date of 11:00am:
RECEIVEDDATETIME + 2 days as DUEDATE;
I have also used the below code to reference TBLCALENDAR to find the # of holidays and weekend days in a date range:
( SELECT COUNT (*) FROM TBLCALENDAR AS C WHERE C.HOLIDAY = 'YES'
AND C.DATE BETWEEN TBLORDERS.RECEIVEDDATETIME
AND TBLORDERS.DUEDATETIME) +
(SELECT COUNT (*) FROM TBLCALENDAR
WHERE DAYOFWK IN (1,7)
AND DATE BETWEEN TBLORDERS.RECEIVEDDATETIME
AND TBLORDERS.UPLOADTIME) AS NONWORKINGDAYS
Expected field output
If order was received between 1/17/2019 4:01pm to 1/18/2019 10:59am = 1/23/2019 11:00am
If order received Current day by 4:00pm 1/18/2019 3:59am= 1/23/2019 by 4:00pm.
RECEIVEDDATETIME DUEDATE
1/17/2019 4:01pm 1/23/2019 11:00am
1/18/2019 10:00am 1/23/2019 4:00pm
Here is a solution without the time logic.
with tblCalendar(DATE, DAYOFWK, DAY, HOLIDAY) as (values
(date('2019-01-19'), 7, 'Saturday', '')
, (date('2019-01-20'), 1, 'Sunday', '')
, (date('2019-01-21'), 2, 'Monday', 'YES')
, (date('2019-01-22'), 3, 'Tuesday', '')
, (date('2019-01-23'), 4, 'Wednesday', 'YES')
, (date('2019-01-24'), 5, 'Thursday', '')
, (date('2019-01-25'), 6, 'Friday', '')
, (date('2019-01-26'), 7, 'Saturday', '')
)
, mytab (RECEIVEDDATE, DAYS2ADD) as (values
(date('2019-01-19'), 2)
, (date('2019-01-20'), 2)
, (date('2019-01-21'), 2)
, (date('2019-01-22'), 2)
)
select m.*, t.date as DUEDATE
--, dayofweek(date) as DAYOFWK, dayname(date) as DAY
from mytab m
, table
(
select date
from table
(
select
date
, sum(case when HOLIDAY='YES' or dayofweek(date) in (7,1) then 0 else 1 end) over (order by date) as dn_
from tblCalendar t
where t.date > m.RECEIVEDDATE
)
where dn_ = m.DAYS2ADD
fetch first 1 row only
) t;
The idea is to enumerate each day of the calendar after the RECEIVEDDATE (1-st parameter) starting from 1 with the following logic: the number of each day increases by 1 if it's non-holiday non-weekend day (the sum(...) over(...) expression).
Finally, we select a date with the corresponding number of days needed to add (2-nd parameter).
Solution idea:
Your tblCalendar is a good idea but I recommend to add the working day information instead of (only) flagging the holidays and weekends. The problem with the "off days" are that after you have figured out how many of them are in the period from your receive date to the receive date + X days you cannot easily add them because there could be other "off dates" in that perios again.
By numbering all the work days you could identify the workday which is closest (equal or bigger) to the receive date. Retrieve its number and add the X days to that number. Retrieve the date that has this work day number and you are fine.
The time logic should be built before that all because it could add another day to the X days.
I'm trying to produce a fully refreshed set of numbers each week, pulling from a table in hive. Right now I using this method:
SELECT
COUNT(DISTINCT case when timestamp between TO_DATE("2016-01-28") and TO_DATE("2016-01-30") then userid end) as week_1,
COUNT(DISTINCT case when timestamp between TO_DATE("2016-01-28") and TO_DATE("2016-02-06") then userid end) as week_2
FROM Data;
I'm trying to get something more along the lines of:
SELECT
Month(timestamp), Week(timestamp), COUNT (DISTINCT userid)
FROM Data
Group By Month, Week
But my week runs Sunday to Saturday. Is there a smarter way to be doing this that works in HIVE?
Solution found:
You can simply create your own formula instead of going with pre-defined function for "week of the year" Advantage: you will be able to take any set of 7 days for a week.
In your case since you want the week should start from Sunday-Saturday we will just need the first date of sunday in a year
eg- In 2016, First Sunday is on '2016-01-03' which is 3rd of Jan'16 --assumption considering the timestamp column in the format 'yyyy-mm-dd'
SELECT
count(distinct UserId), lower(datediff(timestamp,'2016-01-03') / 7) + 1 as week_of_the_year
FROM table.data
where timestamp>='2016-01-03'
group by lower(datediff(timestamp,'2016-01-03') / 7) + 1;
I see that you need the data to be grouped by week. you can just do this :
SELECT weekofyear(to_date(timestamp)), COUNT (DISTINCT userid) FROM Data Group By weekofyear(to_date(timestamp))
I want to just select data for the current week. So...
If the current date is a Monday just select Monday
If the current date is a Tuesday select Monday and Tuesday's data
If the current date is Wednesday select Monday, Tuesday and Wednesday
...and so on. I want it to reset on Sunday and I believe it's some kind of "where" clause just don't know what. As you can see below I'm just counting the number of pieces into the oven and want it to accumulate as the week goes on and then reset on Sunday.
select
count(*) as PiecesIntoOven
from ovenfeederfloat
where...??
Thanks for the help.
If you're looking to do this in Sql Server, see below. Essentially this converts the current date to its numeric (0-6) value, then finds the 0th date for that week and uses it to set the lower bound of the where clause.
select sum(numberofpieces)
from Test
where dateofwork <= getdate()
and dateofwork >= (DATEADD(DAY, DATEPART(WEEKDAY,getdate()) * -1, getdate()) + 1)
Note that the '0' value is impacted by DATEFIRST. https://stackoverflow.com/a/1113891/4824030
I'm not certain how to do this in Oracle. Something like the below should work, but it's being finicky in sqlfiddle.
select sum(numberofpieces)
from Test
where dateofwork <= current_timestamp
and dateofwork >= (((to_char(level+trunc(current_timestamp,'D'),'Day') * -1) + current_timestamp) + 1)