2014-04-29 2 views
1

전체 설치의 마지막 행을이 아니라면 : http://sqlfiddle.com/#!4/1fd0e/5날짜 설정은 SQL 바이올린에

내가 사람의 아이디, 레벨이 포함 된 일부 데이터를 가지고 수준이 같은 범위를 날짜는 다음과 같습니다 :

PID  LVL START_DATE END_DATE 

 1   1 01.01.14 19.03.14 
    1   2 20.03.14 15.08.14 
    1   3 16.08.14 09.10.14 
    1   4 10.10.14 31.12.14 
    2   1 01.01.14 31.12.14 
    3   1 01.01.14 16.01.14 

나는 달의 첫째 날과 달의 마지막 날에 종료 날짜에 시작 날짜를 설정해야합니다. 마지막 날 규칙은 그 사람에 대한 데이터의 마지막 행이 아니면 만 적용합니다.

내가 지금까지 돈을했습니다 무엇 :

PID  LVL START_DATE END_DATE 

 1   1 01.01.14 28.02.14 
    1   2 01.03.14 31.07.14 
    1   3 01.08.14 30.09.14 
    1   4 01.10.14 31.12.14 
    2   1 01.01.14 31.12.14 
    3   1 01.01.14 31.01.14 

:하지만 그냥 내 테스트 - 잘 작동

select 
pid, lvl, 
trunc(start_date, 'month') as start_date, 
case when lead(pid, 1) over (PARTITION BY pid order by end_date) is not null 
    then last_day(add_months(end_date, -1)) 
    else last_day(end_date) 
    end as end_date 
from date_tbl t; 

이 나에게 원하는 출력을 제공합니다 데이터. 내 생산 데이터에 25k + 행의 데이터가 들어있는 표 (마녀는 너무 많은 데이터가 아닙니다)에서 실제로 느리게 수행됩니다.

누구든지 내게 쿼리의 성능을 향상시킬 수있는 힌트를 줄 수 있습니까? 예를 들어 컬럼에 어떤 인덱스를 설정해야합니까? 지금까지 인덱싱 된 유일한 열은 PID 열입니다. 내가 이해 사람이 (PID와 케이스 = 3) 하나 개의 기록을 가지고

, 당신이 하나를 시도 할 수 주시기 바랍니다

+1

"정말 느린"속도는 어떻습니까? 전체 쿼리는 무엇입니까? 25K 행이 있기 때문에 모든 행이 화면에 표시되지 않는다고 가정합니다. 'UPDATE' 문이 있습니까, 아니면 특정 사람에 대한 결과를 제한하는 술어가 있습니까? 대답은 –

답변

0

좋아 녀석을 구축 할 필요가 있다고 생각한다. 짧게하기 위해서 : 그것은 내 잘못이었다. 내 프로 시저에서 위의 쿼리는 일부 하위 쿼리에서 다른 테이블에 LEFT JOIN을 만듭니다.

with dates as (
    select 
    pid, lvl, 
    trunc(start_date, 'month') as start_date, 
    case when lead(pid, 1) over (PARTITION BY pid order by end_date) is not null 
     then last_day(add_months(end_date, -1)) 
     else last_day(end_date) 
     end as end_date 
    from date_tbl t 
), 
    some_other_table as (
    select pid, (...some more columns) 
    from other_table 
) 
select * from (
    select 
    b.pid, -- <== this has to be a.pid. b is much bigger than a! 
    a.start_date, 
    a.end_date 
    from dates a left join some_other_table b on a.pid = b.pid 
) 

전체 쿼리가 훨씬 큽니다.

@jonearles thx에 대한 귀하의 의견입니다. "전체 쿼리는 무엇입니까?" 트랙으로 돌아가는 데 도움이되었습니다. 쿼리를 조각으로 나눠서 실제로 느려지는 부분을 다시 확인하십시오.

0

사실, 스크립트가 잘못된 결과를 생성?

select 
    pid, 
    lvl, 
    trunc(start_date, 'month') as start_date, 
    last_day(add_months(end_date, case when lvl = max(lvl) over (partition by pid) then 0 else -1 end)) end_date 
from date_tbl t; 

난 당신이 컬럼의 인덱스 (PID, LVL 내림차순) 시간을 살 빠지기 죄송

+0

입니다. pid 3 레코드가 올바르지 않습니다. 이는 한 달 동안 만 유효합니다. 기록은 월별로 유효해야합니다. – Jakob