目标:
我正在尝试在给定的一周内更新除最新的HR记录以外的所有记录。
我已经在下面编写了解决方案,但是随着我对oracle date功能的更多了解,我认为它不起作用。
'ww'只允许我在几周内进行分区-从工作日1月1日开始。
'iw'会更近一些,但新的一年将拆分周,并且如果新年从中旬开始,则DEC的最后一周将有记录。
但是,我只需要除了最近的记录之外的所有内容-该周内(星期日-星期六)已更新。
这是到目前为止我尝试过的事情。:
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;
请求的示例数据:
因此,在此示例中,恐怕12月1日会以'iw'算作它自己的一周。 我只想保留/不更新员工22的1/4记录和员工33的1/5记录,以及员工44的1/2记录。
而且,这只是数据的小快照。假设 每周都会创建记录-每位员工都可以追溯到几年前 。
答案 0 :(得分:2)
我在想这样的事情:
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')
);
答案 1 :(得分:0)
周编号及其中的特定日期可以表示为“ WW”或“ IW”规范,但都不符合OP要求。 “ IW”代表根据ISO 8601日期规范的星期;根据公历周编号系统,为“ WW”。 (请参阅https://en.wikipedia.org/wiki/ISO_week_date),问题在于无法确定所需的周六周数。因此,需要第三个选择,那就是计算必要的每周时间。麻烦围绕任何一年的第一个星期,但是我们很容易找到第一个时期的结束数据,从那里开始的日期如下:1)将日期截断到年份。 2)备份1天。 3)找到下一个星期六。结果是第一个期间的最后一天。 4)备份6天到第一个期间的第一天。变成:
select next_day(trunc(sysdate,'yyyy')-1,'sat') - 6;
5)现在,我们可以根据需要计算任意多个星期六至日的日期范围。
有了它,只需找到每个期间内的最大日期并更新其他行即可。
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));