i have a to the find week start date and end date for each date.
for eg:
is it possible to achieve in IBM db2 and Hadoop ?
available fields are date and week id
You can use the DAYOFWEEK_ISO function (which returns the day of week of a date, where 1 = Monday):
with s (dt) as (
values date('2021-10-27')
)
select
dt,
dt - dayofweek_iso(dt) + 1 days as beginning_dt,
dt - dayofweek_iso(dt) + 7 days as end_dt
from s;
DT BEGINNING_DT END_DT
---------- ------------ ----------
10/27/2021 10/25/2021 10/31/2021
1 record(s) selected.
Related
I have table days table.There is oper_day column:
oper_day
01.01.2021
02.01.2021
03.01.2021
**********
**********
31.12.2022
I want to output the maximum date available in a table that is less than the first date of each quarter for example: quarter_date: 01.10.2022 if 30.09.2022 has in a table I give 30.09.2022 else 29.09.2022 .How can I write query?
One could accomplish this by putting the dates into groups by quarter. Then finding the MAX date for that quarter.
SELECT ADD_MONTHS(TRUNC(td.oper_day, 'Q'), 3) next_quarter_begin
,MAX(td.oper_day) max_date_prev_quarter
FROM table_days td
GROUP BY ADD_MONTHS(TRUNC(td.oper_day, 'Q'), 3)
ORDER BY 1
You appear to be asking how to find the last date in each quarter, if so then GROUP BY the data TRUNCated to the start of the quarter and find the maximum date in each quarter (as it will be the latest date before the start of the next quarter).
If you want to ensure that the values are from quarters before the current quarter then you can add a WHERE filter to ignore values in the current quarter or later.
Like this:
SELECT TO_CHAR(TRUNC(oper_day, 'Q'), 'YYYY-Q') AS quarter,
MAX(oper_day) AS last_oper_day_in_quarter
FROM table_name
WHERE oper_day < TRUNC(SYSDATE, 'Q')
GROUP BY TRUNC(oper_day, 'Q')
Which, for the sample data:
CREATE TABLE table_name (oper_day) AS
SELECT DATE '2022-01-01' + LEVEL - 1
FROM DUAL
CONNECT BY DATE '2022-01-01' + LEVEL - 1 <= SYSDATE;
Outputs:
QUARTER
LAST_OPER_DAY_IN_QUARTER
2022-1
31-MAR-22
2022-2
30-JUN-22
2022-3
30-SEP-22
fiddle
I need Dynamic query in BigQuery to find Date of Day Saturday has occurred in First week of Year 2021.
Consider the Day on date of 2022-01-01 is Saturday.
Therefore, I want to extract the date of last Year first week on which the Saturday was occurred.
Try the following:
with sample_dates as (
select date
from unnest(generate_date_array('2022-01-01','2022-12-31')) as date
)
select
date
,(select last_year_date
from unnest(generate_date_array(date_sub(date, INTERVAL 1 YEAR), date-1)) as last_year_date
where extract(week from date) = extract(week from last_year_date)
and extract(dayofweek from date) = extract(dayofweek from last_year_date)
) as last_year_date
from sample_dates
;
Given all of 2022 dates, this provides the same day of week for the same week in the previous year.
For example 2022-01-01 results in 2022-01-02 which is the first Saturday of the first week of last year.
If you're only looking for a single date the main portion would be the generating the appropriate date range with the generate_date_array function and then filtering based on the same week number and dayofweek value.
Use below - should work for any year - just replace 2021 with whatever year you need
select date(2021, 1, 8 - extract(dayofweek from date(2021, 1, 1)))
I think this code can help you!
You can find the first Saturday with a weekly cycle
declare
i number := 0;
date1 date := date '2022-01-01';
d varchar2(20);
begin
while i < 7 loop
SELECT case
when TO_CHAR(date1 + i, 'fmDay') = 'Saturday' then
date1 + i
end "Day"
into d
FROM DUAL;
i := i + 1;
dbms_output.put_line(d);
end loop;
end;
Every month I have to fetch records for the previous month from a Db2 database. How can I write a Db2 query to fetch the last month of data without hard-coding the date range? For example, when run in December 2021, the query would return records dated between '2021-11-01' AND '2021-11-30', and those dates would change dynamically when I run the same query a month later.
It's easy to can precompute the date range in a cte and then use it in the main query. Assuming your table t has a ts column to filter by, you can do:
with
r as (
select
to_date(year(c) || '-' || month(c) || '-01' , 'YYYY-MM-DD') as e,
to_date(year(p) || '-' || month(p) || '-01' , 'YYYY-MM-DD') as b
from (
select current date as c, current date - 1 month as p from sysibm.sysdummy1
) x
)
select *
from t
cross join r
where t.ts >= r.b and t.ts < r.e
See example at db<>fiddle.
There are a few ways to describe the prior month as a date range in a Db2 SQL query. Some datetime SQL functions are not available on Db2 for z/OS, but even then you can still use date arithmetic and the LAST_DAY() function.
First day of last month: LAST_DAY(CURRENT DATE - 2 MONTHS) + 1 DAY
Last day of last month: LAST_DAY(CURRENT DATE - 1 MONTH)
First day of this month: LAST_DAY(CURRENT DATE - 1 MONTH) + 1 DAY
Inclusive-exclusive example (preferred approach):
SELECT ... WHERE someDateTimeColumn >= LAST_DAY(CURRENT DATE - 2 MONTHS) + 1 DAY
AND someDateTimeColumn < LAST_DAY(CURRENT DATE - 1 MONTH) + 1 DAY
Inclusive-inclusive example (calling the DATE() function will prevent implicit type conversion which could skip some some qualifying rows):
SELECT ... WHERE someDateTimeColumn >= LAST_DAY(CURRENT DATE - 2 MONTHS) + 1 DAY
AND DATE(someDateTimeColumn) <= LAST_DAY(CURRENT DATE - 1 MONTH)
If you're querying Db2 for LUW v11.1 or newer, you can also call the THIS_MONTH() function to get the first day of an input month.
First day of last month: THIS_MONTH(CURRENT DATE - 1 MONTH)
First day of this month: THIS_MONTH(CURRENT DATE)
Inclusive-exclusive example:
SELECT ... WHERE someDateTimeColumn >= THIS_MONTH(CURRENT DATE - 1 MONTH)
AND someDateTimeColumn < THIS_MONTH(CURRENT DATE)
Objective:
I'm trying to update all but the latest HR record within a given week.
I've written the solution below, but as I reviewed oracle date functionality more, I think it won't work..
'ww' would only let me partition on weeks - starting on the weekday JAN 1 occurs.
'iw' would be closer, but the weeks would be split at new year, and there would be a record remaining from the last week of DEC - if the new year starts mid week..
However, I'm just needing all but the latest record - within that week (sun - Sat) updated.
here's what I've attempted so far.. :
UPDATE hr_info.hr_hours
SET expire_date = SYSDATE, deleted = 'Y', update_date = SYSDATE
WHERE (ROWID, compnay_id) IN (SELECT ROWID, compnay_id
FROM (SELECT hrs.*,
ROW_NUMBER ()
OVER (
PARTITION BY emp_nbr,
TO_CHAR (
hrs_effective_date + 1,
'iw'),
TO_CHAR (
hrs_effective_date,
'yy')
ORDER BY
hrs_effective_date DESC)
rown
FROM hr_info.hr_hours hrs
WHERE compnay_id = 3
AND expire_date =
TO_DATE ('12/31/9999',
'mm/dd/yyyy'))
WHERE rown > 1;
COMMIT;
requested example data :
So, in this example, I'm afraid Dec 1 would count as its own week with 'iw'.
I'd just want to keep / not update the 1/4 record for employee 22 and the 1/5 record for employee 33, and the 1/2 record for employee 44.
And, this is just a small snapshot of the data. Records would hypothetically be created on every week - going back years for each employee.
I am thinking something like this:
UPDATE hr_info.hr_hours h
SET expire_date = SYSDATE,
deleted = 'Y',
update_date = SYSDATE
WHERE h.hrs_effective_date < (
SELECT MAX(h2.hrs_effective_date)
FROM hr_info.hr_hours h2
WHERE h2.company_id = h.company_id AND
TRUNC(hr2.hrs_effective_date, 'IW') = TRUNC(hr.hrs_effective_date, 'IW')
);
Week numbering and thus specific dates within them can be represented 'WW' or 'IW' specification but neither serve OP requirements. The 'IW' represents weeks according to the ISO 8601 date specification; 'WW' according to Gregorian week numbering system. (see https://en.wikipedia.org/wiki/ISO_week_date ) The trouble is neither identify weeks in the required Sun-Sat period. So a third option is needed and that is to calculate the necessary weekly periods. The trouble revolves around the 1st week of the any given year, but we easily find the ending data of the 1st period and from there the beginning date as follows: 1) Truncate the date to the year. 2) Backup 1 day. 3) Find the next Saturday. Result is last day of 1st period. 4) Backup 6 days to the first day of 1st period. That becomes:
select next_day(trunc(sysdate,'yyyy')-1,'sat') - 6;
5) We can now calculate any Sat-Sun dates ranges for as many periods as we want.
With that in hand just find the max date within each period and update other rows.
update hr_hours
set deleted='Y'
, update_date = sysdate
, expire_date = sysdate
where 1=1
and expire_date = date '9999-12-31'
and (employee_nbr,hrs_effective_date) not in
(with date_range as (select date '2019-01-04' sdt, date '2019-03-01' edt from dual) -- get full date range
, weeks as (select level-1 wk from dual connect by level <= (select trunc( (edt-sdt)/7)+1 from date_range)) -- calc number of weekly periods
, yr1st as (select next_day(trunc(sdt,'yyyy'), 'Sat') - 6 p1_start from date_range) -- calculate 1st preiod start date
, periods as (select p1_start+(7*wk) period_begin, p1_start+(7*wk)+6 period_end from yr1st, weeks) -- calculate each period start and end date
select employee_nbr, eff_date
from (
select h.employee_nbr,max(h.hrs_effective_date) eff_date,p.period_begin
from hr_hours h
, periods p
where 1 = 1
and h.hrs_effective_date between p.period_begin and p.period_end
group by h.employee_nbr,p.period_begin));
I have a table with date field and there will be multiple entries for each day. I need to get the count of weekdays having at least one entry in that weekday.
If the date range is 27-Feb-12 till 2-Apr-12 then there are 26 week days and it needs to return 26 if we have entries in all weekdays and a lesser count if there is no entry on a particular day.
Say a table Transaction with tid, type, createddate.
Can someone please suggest me a good SQL approach ? I am running on a Oracle DB
Try breaking down the problem into multiple smaller problems. Here's how..(I am using march-10 instead of april 2nd in your example, to keep the data set smaller).
Get all the dates between the two dates.
select to_date('27-feb-2012','dd-mon-yyyy') + level -1
from dual
connect by level < ( to_date('10-mar-12','dd-mon-yy') -
to_date('27-feb-2012','dd-mon-yyyy') +2
)
TO_DATE('
---------
27-FEB-12
28-FEB-12
29-FEB-12
01-MAR-12
02-MAR-12
03-MAR-12
04-MAR-12
05-MAR-12
06-MAR-12
07-MAR-12
08-MAR-12
next, get the weekdays out of this result set..
with all_days as (
select to_date('27-feb-2012','dd-mon-yyyy') + level -1 date1
from dual
connect by level < ( to_date('10-mar-12','dd-mon-yy') -
to_date('27-feb-2012','dd-mon-yyyy') +2
)
)
select date1,
to_char(date1,'D'),
to_char(date1,'Day') Day
from all_days
where to_number(to_char(date1,'D')) between 2 and 6 -- monday through friday
/
DATE1 T DAY
--------- - ---------
27-FEB-12 2 Monday
28-FEB-12 3 Tuesday
29-FEB-12 4 Wednesday
01-MAR-12 5 Thursday
02-MAR-12 6 Friday
05-MAR-12 2 Monday
06-MAR-12 3 Tuesday
07-MAR-12 4 Wednesday
08-MAR-12 5 Thursday
09-MAR-12 6 Friday
--and finally, your exists logic to check if there is any data for this date in your table.
with all_days as (
select to_date('27-feb-2012','dd-mon-yyyy') + level -1 date1
from dual
connect by level < ( to_date('10-mar-12','dd-mon-yy') -
to_date('27-feb-2012','dd-mon-yyyy') +2
)
)
select date1,
to_char(date1,'D'),
to_char(date1,'Day') Day
from all_days
where to_number(to_char(date1,'D')) between 2 and 6 -- monday through friday
and exists (
select 1
from your_table yt
where yt.date_column = all_days.date_column
)
There are 25 total business days between your dates in 2013 - I used current year. With my hypothetical data you will get 17 total working days with entries. To see all days comment SUM() part and uncomment Start_Date... and other columns. Then you can count visually to check results:
SELECT SUM(CASE WHEN Entry_Val > 0 THEN 1 ELSE 0 END) entry_days --, Start_Date, Wk_Day, Day#, entry_val, lvl
FROM
(
SELECT TO_CHAR(TO_DATE('27-FEB-12') + LEVEL-1, 'DD-MON-YYYY') Start_Date
, TO_CHAR(TO_DATE('27-FEB-12') + LEVEL-1, 'DY') Wk_Day
, TO_CHAR(TO_DATE('27-FEB-12') + LEVEL-1, 'D' ) Day#
, MOD(LEVEL, 3) Entry_Val -- Hypot. entry day - count only days with entry_val > 0 --
, LEVEL lvl -- added for clarity
FROM dual CONNECT BY LEVEL <= (SELECT to_date('02-APR-12') - to_date('27-FEB-12') days_btwn FROM dual)
)
WHERE Wk_Day NOT IN ('SAT', 'SUN') -- OR -- Day# NOT IN (1, 7)
/
ENTRY_DAYS
--------
17
I'm interpreting this question a little differently. #Pradeep, is this what you're after?
SELECT COUNT(DISTINCT TRUNC(CreatedDate))
FROM Transaction
WHERE TRUNC(CreatedDate) BETWEEN DATE '2012-02-27' AND DATE '2012-04-02'
AND TO_CHAR(CreatedDate, 'DY') NOT IN ('SAT', 'SUN')
If you have entries for all Monday-Friday days between 2/27/2012 and 4/2/2012, the result of this query will be 26. It won't matter how many entries there are for any given day, as long as each day has at least one.
If you don't have any records for two of the days (say 2/28 and 3/22) the result will be 24.
Note that I used TRUNC in the first and third lines above in case your CreatedDate column includes a time component. If it doesn't you can do without the TRUNC.
select to_date('02-04-2012','DD-MM-YYYY')-
to_date('27-02-2012','DD-MM-YYYY')-
2*(to_char(to_date('02-04-2012','DD-MM-YYYY'),'WW')-
to_char(to_date('27-02-2012','DD-MM-YYYY'),'WW'))+1 from dual;