我正在尝试使用中断处理日期查找给定值的后续数据的最小和最大处理日期(请注意,周末不处理行,我不想将它们分成两个不同的集合,如果它们具有相同的价值)
SELECT 1, 'A',to_date('10/01/2012','dd/mm/yyyy'), 10, to_date('11/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('11/01/2012','dd/mm/yyyy'), 10, to_date('12/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('12/01/2012','dd/mm/yyyy'), 9, to_date('13/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('13/01/2012','dd/mm/yyyy'), 9, to_date('14/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('16/01/2012','dd/mm/yyyy'), 9, to_date('17/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('17/01/2012','dd/mm/yyyy'), 10, to_date('18/01/2012','dd/mm/yyyy') FROm DUAL
UNION ALL SELECT 1, 'A',to_date('18/01/2012','dd/mm/yyyy'), 10, to_date('19/01/2012','dd/mm/yyyy') FROm DUAL;
我的尝试(我知道错了)
SELECT id, cd, value, min(p_dt) min_dt, max(p_dt) max_dt FROM T
group by id, cd, value;
返回
ID CD VALUE MIN_DT MAX_DT
----------------------------------------------------------------------------------
1 A 9 January, 12 2012 00:00:00+0000 January, 16 2012 00:00:00+0000
1 A 10 January, 10 2012 00:00:00+0000 January, 18 2012 00:00:00+0000
我想要归来的是
ID CD VALUE MIN_DT MAX_DT
----------------------------------------------------------------------------------
1 A 9 January, 12 2012 00:00:00+0000 January, 16 2012 00:00:00+0000
1 A 10 January, 10 2012 00:00:00+0000 January, 11 2012 00:00:00+0000
1 A 10 January, 17 2012 00:00:00+0000 January, 18 2012 00:00:00+0000
我尝试了不同的方法来查询,但我无法提供有效的查询。
答案 0 :(得分:0)
不确定您想要什么...您没有按日期分区的正确数据。您的日期是唯一的,除非您的意思是您的i_dt必须相等p_dt。即使您按日期而不是按值进行分区,您也会获得所有行的回报,就像在简单选择中一样。 在我的例子中,我按值进行分区。在唯一值内可能只有一个最大值和一个最小值。检查输出:
SELECT id, cd, i_dt, p_dt, value
, To_Char(MIN(p_dt) OVER (PARTITION BY value), 'Mon, DD YYYY HH24:MI:SS') min_dt
, To_Char(MAX(p_dt) OVER (PARTITION BY value), 'Mon, DD YYYY HH24:MI:SS') max_dt
FROM t
/
ID CD I_DT P_DT VALUE MIN_DT MAX_DT
---------------------------------------------------------------------------------------
1 A 1/14/2012 1/13/2012 9 Jan, 12 2012 00:00:00 Jan, 16 2012 00:00:00
1 A 1/17/2012 1/16/2012 9 Jan, 12 2012 00:00:00 Jan, 16 2012 00:00:00
1 A 1/13/2012 1/12/2012 9 Jan, 12 2012 00:00:00 Jan, 16 2012 00:00:00
1 A 1/19/2012 1/18/2012 10 Jan, 10 2012 00:00:00 Jan, 18 2012 00:00:00
1 A 1/18/2012 1/17/2012 10 Jan, 10 2012 00:00:00 Jan, 18 2012 00:00:00
1 A 1/12/2012 1/11/2012 10 Jan, 10 2012 00:00:00 Jan, 18 2012 00:00:00
1 A 1/11/2012 1/10/2012 10 Jan, 10 2012 00:00:00 Jan, 18 2012 00:00:00
答案 1 :(得分:0)
本网站上有许多其他问题,希望解决同样的问题。例如here和here,这些只是我提供答案的问题。
由于要求忽略周末,这个问题有点复杂。这似乎相对简单,我很快就会解释。
您的问题不包括表格中所有列的列名称。我假设第一个日期是进程日期,另一个日期对于此查询并不重要。这可能是错误的假设。
从问题来看,如果在工作日(周一至周四)第二天有匹配的行,则看起来组会存在。对于星期五,在接下来的星期一需要有匹配的行。我处理这个问题,如果是星期五则增加3天,或者在其他情况下增加一天。
示例查询如下所示,并显示SQLFiddle is also available。
希望这可以解决您的问题。
with test_data as (
SELECT 1 as id, 'A' as cd,to_date('10/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('11/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL
SELECT 1 as id, 'A' as cd,to_date('11/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('12/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL
SELECT 1 as id, 'A' as cd,to_date('12/01/2012','dd/mm/yyyy') as p_date, 9 as value, to_date('13/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL
SELECT 1 as id, 'A' as cd,to_date('13/01/2012','dd/mm/yyyy') as p_date, 9 as value, to_date('14/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL
SELECT 1 as id, 'A' as cd,to_date('16/01/2012','dd/mm/yyyy') as p_date, 9 as value, to_date('17/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL
SELECT 1 as id, 'A' as cd,to_date('17/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('18/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL UNION ALL
SELECT 1 as id, 'A' as cd,to_date('18/01/2012','dd/mm/yyyy') as p_date, 10 as value, to_date('19/01/2012','dd/mm/yyyy') as some_other_date FROm DUAL
)
select
id,
cd,
value,
block_num,
min(p_date) as process_start_date,
max(p_date) as process_end_date
from (
select
id,
cd,
value,
p_date,
sum(is_block_start) over (partition by id, cd, value order by p_date) as block_num
from (
select
id,
cd,
value,
p_date,
-- get end date of previous block
case when lag(case when to_char(p_date, 'DY') = 'FRI' then p_date+3 else p_date+1 end)
over (partition by id, cd, value order by p_date) = p_date then 0 else 1 end as is_block_start
from test_data
-- Make sure that the data definitely doesn't include Sat or Sun because this could just confuse things
where to_char(p_date, 'DY') not in ('SAT', 'SUN')
)
)
group by id, cd, value, block_num
order by id, cd, value, block_num