2013-07-25 7 views
2

Я видел некоторые блестящие ответы здесь, и мне нужно исправить. Я пока не хочу создавать таблицу или ETL, и я надеялся создать простой доступ к базе данных, к которой пользователи могли сначала получить доступ к тесту.Как получить начальную/конечную дату с одного столбца даты -oracle

таблица имеет пункт #, item_ticket_color #, maint_date и другие столбцы tick_col обновляется иногда , но и другие столбцы в таблице, как хорошо. Если какой-либо другой столбец обновлен или изменен tick_col выполняет итерации. Мне нужно отфильтровать эти данные, чтобы получить ожидаемый результат ниже, и вам нужна помощь , пытаясь понять, как я могу это сделать. Ищу прямой SQL, если это возможно

ITEM......................TICK_COL................. MAINT_DATE 

21524804....................RIBG...................1/1/0001 
21524804....................RIBG...................6/15/2008 6:52:57 AM 
21524804....................RIBG...................6/25/2008 11:31:03 AM 
21524804....................RIBG...................6/28/2008 4:12:21 AM 
21524804....................RIWH...................9/20/2008 6:36:24 AM 
21524804....................RIGR...................9/23/2008 6:36:44 AM 
21524804....................RIGR...................9/30/2008 6:37:42 AM 
21524804....................RIWH...................10/31/2008 6:37:27 AM 
21524804....................RIWH...................11/1/2008 6:36:41 AM 
21524804....................RIGR...................3/11/2009 6:01:43 PM 
21524804....................RIGR...................7/28/2009 6:37:11 AM 
21524804....................RIGR...................10/8/2009 6:37:00 AM 
21524804....................RIBS...................11/20/2009 6:37:58 AM 
21524804....................RIBS...................5/18/2010 6:37:07 AM 
21524804....................RIBS...................9/16/2010 6:38:11 AM 
21524804....................RIBS...................8/13/2012 10:39:44 AM 
21524804....................RIBS...................3/12/2013 6:46:08 AM 
21524804....................RIBS...................3/17/2013 9:25:31 AM 
21524804....................RIBS...................3/27/2013 6:52:57 AM 
21524804....................RIBS...................7/25/2013 6:41:51 AM 

Я ожидал увидеть это ниже, где он показывает начальную и конечную дату для каждого из сценариев, где цвет билет изменен .:

21524804.....RIBG.....10101........20080919 

21524804.....RIWH.....20080920.....20080922 

21524804.....RIGR.....20080923.....20081030 

21524804.....RIWH.....20081031.....20090310 

21524804.....RIGR.....20090311.....20091119 

21524804.....RIBS.....20091120.....20130725 

SQLFiddle here.

здесь новый код, основанный на вкладе Jasti, я сделал некоторые дополнительные изменения, но это именно то, что я хотел

SELECT item, 
     tick_col, 
     from_dt, 
     CASE 
      WHEN LEAD (from_dt) OVER (PARTITION BY item ORDER BY from_dt) - 1 
        IS NULL 
      THEN 
      SYSDATE 
      ELSE 
      LEAD (from_dt) OVER (PARTITION BY item ORDER BY from_dt) - 1 
     END 
      TO_DATE 
    FROM ( SELECT ITEM, 
       TICK_COL, 
       MIN (MAINT_DATE) AS from_dt, 
       MAX (MAINT_DATE) AS to_dt 
      FROM (SELECT SUM (start_of_group) OVER (ORDER BY maint_date) AS sm, 
         ITEM, 
         TICK_COL, 
         maint_date 
        FROM (SELECT ITEM, 
           TICK_COL, 
           maint_date, 
           CASE 
            WHEN LAG (TICK_COL, 1, TICK_COL) 
              OVER (ORDER BY maint_date) = 
              TICK_COL 
            THEN 
             0 
            ELSE 
             1 
           END 
            start_of_group 
          FROM mytable)) 
     GROUP BY ITEM, TICK_COL, sm 
     ORDER BY sm) 
+0

Я добавил решение и обновленную ссылку SQL скрипку. Прокомментируйте, если это не сработает для вас. – Jasti

+0

благодарит Jasti, абсолютно блестящий, мне пришлось что-то добавить к нему, чтобы получить то, что я хотел, но он работает –

+1

Опубликуйте решение в качестве ответа и отметьте его таким образом. Не обновляйте вопрос с помощью решения, так как оно должно быть ** Вопрос ** – Shaihi

ответ

0

Попробовать и посмотреть, если этот запрос работает.

+0

Я сделал SQL Fiddle –

0

Вы можете использовать min и max, чтобы получить вторую часть. Я не уверен, что вы ищете в первой части, кроме стандартного выбора.

SELECT ITEM, TICK_COL, MIN(MAINT_DATE) AS startDate, MAX(MAINT_DATE) AS endDate 
FROM yourTableName 
GROUP BY ITEM, TICK_COL 
1

Я также добавил запрос для вашей первой части. Следующий запрос должен решить оба требования. Этот запрос группирует изделия до изменения TICK_COL и рассчитать максимальную и минимальные даты для этой конкретной группы

select ITEM, TICK_COL, MIN(MAINT_DATE) AS from_dt, MAX(MAINT_DATE) AS to_dt from 
(
    select sum(start_of_group) over (order by maint_date) as sm, ITEM, TICK_COL, maint_date from 
    (
    select ITEM, TICK_COL,maint_date, 
     case 
     when 
      lag(TICK_COL,1,TICK_COL) over (order by maint_date) = TICK_COL then 0 
      else 1 
     end start_of_group 
    from mytable 
) 
) group by ITEM, TICK_COL,sm order by sm 

Обновленного SQL Fiddle here

+0

Я сделал SQL Fiddle на своих данных, и я использовал ваш запрос, даты начала и окончания отключены, пожалуйста, посмотрите на мои ожидаемые результаты .... –

+0

Фактически даты начала хороши, но даты окончания не установлены –

+1

@CM - если это вам помогло, то, по крайней мере, вы можете его перенести. Если это ответ, отметьте его как таковой. – Shaihi

0

Варианта на основе обнаружения начала и конца периода, а затем рассчитать даты. (Почти такое же решение может быть найдено here.)

SQLFiddle

with marked_set as (
    -- mark start and end of each maintenance period 
    select 
    item, 
    tick_col, 
    maint_date, 
    decode(nvl(prev_tick, tick_col||'x'), tick_col, 0, 1) is_start, 
    decode(nvl(next_tick, tick_col||'x'), tick_col, 0, 1) is_end 
    from (
    select 
     item, 
     tick_col, 
     maint_date, 
     lag(tick_col) over (partition by item order by maint_date) prev_tick, 
     lead(tick_col) over (partition by item order by maint_date) next_tick 
    from 
     mytable 
) 
), 
boundary_set as (
    -- Leave only start and end of each period 
    -- and get dates from previous and next lines 
    select 
    item, 
    tick_col, 
    maint_date, 
    is_start, 
    is_end, 
    (lag(maint_date) over (
     partition by item order by maint_date) 
    )           prev_maint_date, 
    (lead(maint_date,1,maint_date) over (
     partition by item order by maint_date 
    ) 
    )           next_maint_date 
    from 
    marked_set 
    where 
    1 in (is_start, is_end) 
), 
maintenance_sequence as (
    -- Calculate start and end dates for each maintenance period 
    select distinct 
    item, 
    tick_col, 
    decode(is_start, 
     1, maint_date, 
     prev_maint_date 
    )      start_date, 
    decode(is_end, 
     1, next_maint_date, 
     (lead(next_maint_date,1,next_maint_date) 
     over (partition by item order by maint_date) 
    ) 
    )     end_date 
    from 
    boundary_set 
) 
select 
    -- Final formatting and ordering. 
    -- For end date of last period get exact date, for others get previous date 
    -- because it's date of start for maintenance of next item. 
    item, 
    tick_col, 
    to_char(start_date, 'yyyymmdd') maint_start, 
    decode((lead(end_date) over (partition by item order by start_date)), 
    null, to_char(end_date, 'yyyymmdd'), 
    to_char(end_date - 1, 'yyyymmdd') 
) 
    maint_end 
from 
    maintenance_sequence 
order by 
    maint_start