我想获取两个日期之间每周的开始和结束日期。日期的格式为dd / mm / yyy hh24:mi:ss。我需要采用dd / mm / yyyy hh24:mi:ss格式的星期,因为我必须用时间计算一周的开始和结束之间的天数和小时数
我写了这句话
WITH
date_range AS (
SELECT
pdm.des_comercial serie,
pdm.id_material codserie,
ri.id_accion intervencion,
TO_CHAR(NVL(ri.fecha_salida_rev, SYSDATE), 'dd/mm/RRRR') fecha1,
to_char((CASE
WHEN ri.fecha_salida_rev > TO_DATE('18/06/2019', 'dd/mm/yyyy') THEN TO_DATE('18/06/2019', 'dd/mm/yyyy')
WHEN ri.fecha_salida_Rev IS NULL THEN TO_DATE('18/06/2019', 'dd/mm/yyyy')
ELSE ri.fecha_salida_Rev
END),'dd/mm/yyyy hh24:mi:ss') fechasalida,
to_char((CASE
WHEN ri.fecha_entrada_rev < TO_DATE('01/06/2019', 'dd/mm/yyyy') THEN TO_DATE('01/06/2019', 'dd/mm/yyyy')
ELSE ri.fecha_entrada_Rev
END),'dd/mm/yyyy hh24:mi:ss') fechaentrada
,
ri.cod_taller_rev,
ri.COD_MATRICULA,
ri.fecha_entrada_rev start_date,
ri.fecha_salida_rev end_date
FROM
r_intervencion ri,
planificador.pl_dh_material pdm
WHERE
ri.id_accion = ri.amortizada_por
AND ri.causa_entrada = 1
AND ri.tipo_accion = 1
AND pdm.id_material = ri.cod_serie
AND pdm.hasta = 99999999
AND ri.ID_ACCION = 'IM4'
AND ri.fecha_salida_rev BETWEEN TO_DATE('01/06/2019', 'dd/mm/yyyy') AND TO_DATE('18/06/2019', 'dd/mm/yyyy')
),
semanas AS (
SELECT LEVEL "Week"
,to_char(to_date(start_date,'dd/mm/yyyy hh24:mi:ss') + (7 * (LEVEL - 1)),'IW') startweek
,to_char(to_date(start_date ,'dd/mm/yyyy hh24:mi:ss')+ (7 * (LEVEL - 1)),'IW') + 6 endweek
,TO_CHAR(start_date + (7 * (LEVEL - 1)),'IW') "Iso Week",
serie,
codserie,
intervencion,
cod_taller_rev,
cod_matricula,
fechaentrada,
fechasalida,
start_date,
end_date
FROM date_range
CONNECT BY LEVEL <= (to_char(To_date(end_date,'dd/mm/yyyy hh24:mi:ss'),'IW') - to_char(To_date(start_date,'dd/mm/yyyy hh24:mi:ss'),'IW')) / 7 + 1
)
SELECT startweek,
endweek,
to_date(endweek,'dd/mm/yyyy hh24:mi:ss') - to_date(startweek,'dd/mm/yyyy hh24:mi:ss') dias,
serie,
codserie,
intervencion,
cod_taller_rev,
cod_matricula,
start_Date,
end_date,
fechaentrada,
fechasalida,
rd.descripcion
FROM semanas,r_depositos rd
WHERE cod_taller_rev = rd.cod_deposito
执行它,我得到
查询执行失败
SQL Error [1840] [22008]: ORA-01840: ORA-01840: input value not long enough for date format
错误在于
,to_char(to_date(start_date,'dd/mm/yyyy hh24:mi:ss') + (7 * (LEVEL - 1)),'IW') startweek
,to_char(to_date(start_date ,'dd/mm/yyyy hh24:mi:ss')+ (7 * (LEVEL - 1)),'IW') + 6 endweek
如何获取格式为dd / mm / yyyy hh24:mi:ss的开始周和结束周
编辑
start_date end_date
20/05/2019 20:00:00 05/06/2019 08:00:00
周
20/05/2019 20:00:00 26/05/2019 -> 6 days and xxx hours
27/05/2019 02/06/2019 -> 7 days
03/06/2019 05/06/2019 08:00:00 -> 3 days and xxx hours
我需要计算每周的天数和小时数。
For example between 20/05/2019 20:00:00 and 26/05/2019
and last one between 03/06/2019 and 05/06/2019 08:00:00
我的问题是计算
to_date(endweek,'dd/mm/yyyy hh24:mi:ss') - to_date(startweek,'dd/mm/yyyy hh24:mi:ss') dias,
endweek and startweek have to have dd/mm/yyyy hh24:mi:ss
答案 0 :(得分:0)
您的endweek
计算是
to_char(to_date(start_date ,'dd/mm/yyyy hh24:mi:ss')+ (7 * (LEVEL - 1)),'IW') + 6 endweek
这将尝试将数字6添加到字符串中。我怀疑你想要的是
to_char(to_date(start_date ,'dd/mm/yyyy hh24:mi:ss') + (7 * (LEVEL - 1) + 6),'IW') endweek
在这里,我已经移动了+ 6
,所以您要在日期值(而不是字符串)上加上6。
好运。
答案 1 :(得分:0)
我的问题是计算
to_date(endweek,'dd/mm/yyyy hh24:mi:ss') - to_date(startweek,'dd/mm/yyyy hh24:mi:ss') dias, endweek and startweek have to have dd/mm/yyyy hh24:mi:ss
Oracle日期以内部格式存储,您通常不必担心。您的应用程序或客户端会根据日期或会话的NLS设置将日期格式设置为字符串。
当您执行以下操作时:
to_date(endweek,'dd/mm/yyyy hh24:mi:ss')
您确实在做
to_date(to_char(endweek),'dd/mm/yyyy hh24:mi:ss')
,由于没有为隐式to_char()
调用指定显式格式掩码,因此它使用了当前会话的NLS设置。根据设置,它可能会出错;或可能破坏值-例如混合使用YY和YYYY蒙版可能会失去世纪,将2019转换为0019。(鉴于您遇到的错误,您的NLS设置可能不寻常吗?)。
充其量,您需要将日期值转换为字符串,然后再返回完全相同的日期值,这毫无意义。您没有更改datem的 format ,因为它没有一个。中间的字符串可以,但是您没有使用它,也不能进行计算(至少没有按原样转换回日期,这同样没有意义。)
Oracle还具有其他操作日期值的功能,包括trunc()
,所以我认为您可能需要这样-用三种方式显示差异,尽管还有其他方式,但您可以根据需要格式化最后一种:
with date_range (start_date, end_date) as (
-- dummy data from your example
select to_date('20/05/2019 20:00:00', 'DD/MM/YYYY HH24;MI:SS') as start_date,
to_date('05/06/2019 08:00:00', 'DD/MM/YYYY HH24;MI:SS') as end_date
from dual
),
semanas as (
select level as week,
start_date,
end_date,
greatest(trunc(start_date + (7 * (level - 1)), 'IW'), start_date) as start_week,
least(trunc(start_date + (7 * level), 'IW'), end_date) as end_week
from date_range
connect by level <= (trunc(end_date, 'IW') - trunc(start_date, 'IW')) / 7 + 1
)
select week,
to_char(start_week, 'IW') as iso_week,
to_char(start_week, 'DD/MM/YYYY HH24:MI:SS') as start_week,
to_char(end_week, 'DD/MM/YYYY HH24:MI:SS') as end_week,
end_week - start_week as diff_num,
numtodsinterval(end_week - start_week, 'DAY') as diff_interval,
to_char(date '1999-12-31' + (end_week - start_week), 'FMDD "days" HH24 "hours"') as diff_words
from semanas;
WEEK IS START_WEEK END_WEEK DIFF_NUM DIFF_INTERVAL DIFF_WORDS
---------- -- ------------------- ------------------- ---------- ------------------- ----------------
1 21 20/05/2019 20:00:00 27/05/2019 00:00:00 6.16666667 +06 04:00:00.000000 6 days 4 hours
2 22 27/05/2019 00:00:00 03/06/2019 00:00:00 7 +07 00:00:00.000000 7 days 0 hours
3 23 03/06/2019 00:00:00 05/06/2019 08:00:00 2.33333333 +02 08:00:00.000000 2 days 8 hours
根据目前的情况,connect by
仅在date_range
CTE生成单个值时才能正常工作;如果您实际上从实际查询中返回了多行,那么您将不得不做更多的工作,或者切换到递归CTE,或者交叉联接/应用,这取决于您的Oracle版本。