2016-01-12 6 views
0

Я работаю над базой данных оракула sql. У меня есть таблица с id, begindate и enddate.развернуть строку в разных строках

Например:

employee | begindate | enddate 
john  | 18/02/2015 | 18/02/2015 
john  | 19/02/2015 | 21/02/2015 

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

john | 18/02/2015 | 18/02/2015 
john | 19/02/2015 | 19/02/2015 
john | 20/02/2015 | 20/02/2015 
john | 21/02/2015 | 21/02/2015 

Таким образом, мой оператор выбора будет иметь в этом примере всего 4 строки.

Есть ли у кого-то идеи, как я могу это сделать?

+0

Может помочь справочная таблица с возможными датами. – jarlh

+0

как jarlh сказал, если у вас есть измерение времени, у которого есть все даты года, вы можете присоединиться к игре вверх. – sagi

ответ

3

Настройка Oracle:

CREATE TABLE employees (employee, begindate, enddate) AS 
SELECT 'john', DATE '2015-02-18', DATE '2015-02-18' FROM DUAL UNION ALL 
SELECT 'john', DATE '2015-02-19', DATE '2015-02-21' FROM DUAL; 

Запрос:

SELECT e.employee, 
     t.COLUMN_VALUE AS begindate, 
     t.COLUMN_VALUE AS enddate 
FROM employees e, 
     TABLE(
     CAST(
      MULTISET(
      SELECT e.begindate + LEVEL - 1 
      FROM DUAL 
      CONNECT BY LEVEL <= e.enddate - e.begindate + 1 
      ) 
      AS SYS.ODCIDATELIST 
     ) 
     ) t; 

Результаты:

EMPLOYEE BEGINDATE ENDDATE 
-------- --------- --------- 
john  18-FEB-15 18-FEB-15 
john  19-FEB-15 19-FEB-15 
john  20-FEB-15 20-FEB-15 
john  21-FEB-15 21-FEB-15 
+0

У меня есть другой вопрос с этим примером. Я хочу добавить столбец, в котором говорится, что это первый элемент блока, средний элемент или конечный элемент (или единственный элемент). Например, в приведенном выше примере: 19feb - это первый элемент, 20 feb - элемент middele и 21feb последний элемент. 18feb не был периодом, поэтому флаг должен быть только элементом. – Bigjo

+0

'CASE WHEN e.begindate = e.enddate THEN 'only' КОГДА t.COLUMN_VALUE = e.begindate THEN 'first' WHEN t.COLUMN_VALUE = e.enddate THEN 'last' ELSE 'middle' END' – MT0

0

Решение будет очень похоже на ORACLE SQL:Get all integers between two numbers с «двумя номерами», являющимся диапазоном дат между begindate и enddate.

Что-то вроде:

Create Table test (employee varchar(50), begindate date, enddate date); 

Insert Into test (employee, begindate, enddate) 
Values ('john', TO_DATE('18/02/2015', 'dd/mm/yyyy'), TO_DATE('18/02/2015', 'dd/mm/yyyy')); 

Insert Into test (employee, begindate, enddate) 
Values ('john', TO_DATE('19/02/2015', 'dd/mm/yyyy'), TO_DATE('21/02/2015', 'dd/mm/yyyy')); 

А потом

Select employee, enumdate As begindate, enumdate As enddate 
From test Cross Apply (
    Select begindate + rownum - 1 As enumdate 
    From Dual 
    Connect By Level <= enddate - begindate + 1 
) enum; 
+0

Оператор SELECT с ошибкой: SQL-Fehler: ORA-00933: команда SQL не выполнена должным образом 00933. 00000 - «Команда SQL не выполнена должным образом» – GreenTurtle

+2

'CROSS APPLY' действителен только в Oracle 12. – MT0

+0

Извините, не могу проверить он сам в данный момент. –

1

Вот альтернативный ответ, используя подключения непосредственно на столе:

with test as (select 'john' employee, to_date('18/02/2015', 'dd/mm/yyyy') begindate, to_date('18/02/2015', 'dd/mm/yyyy') enddate from dual union all 
       select 'john' employee, to_date('19/02/2015', 'dd/mm/yyyy') begindate, to_date('21/02/2015', 'dd/mm/yyyy') enddate from dual) 
select employee, 
     begindate + level - 1 begindate, 
     begindate + level - 1 enddate 
from test 
connect by prior employee = employee 
      and prior begindate = begindate 
      and prior sys_guid() is not null 
      and begindate + level - 1 <= enddate; 

EMPLOYEE BEGINDATE ENDDATE 
-------- ---------- ---------- 
john  18/02/2015 18/02/2015 
john  19/02/2015 19/02/2015 
john  20/02/2015 20/02/2015 
john  21/02/2015 21/02/2015 

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