Oracle 10g: вставка пропущенных дат в таблицу с другими значениями - PullRequest
0 голосов
/ 22 мая 2018

В этом вопросе я смог вставить дату в

|----------|----------|
|  DT      |  FLAG    |
|----------|----------|
| 2015-MAY |  E       |
| 2015-JUN |  H       |
| 2015-OCT |  E       |
| 2016-FEB |  E       |
|----------|----------|

, чтобы получить (пропущенные месяцы вставляются с FLAG V)

|----------|----------|
|  DT      |  FLAG    |
|----------|----------|
| 2015-MAY |  E       |
| 2015-JUN |  H       |
| 2015-JUL |  V       |
| 2015-AUG |  V       |
| 2015-SEP |  V       |
| 2015-OCT |  E       |
| 2015-NOV |  V       |
| 2015-DEC |  V       |
| 2016-JAN |  V       |
| 2016-FEB |  E       |
|----------|----------|

Со следующим кодом:

CREATE OR REPLACE PROCEDURE FILL_DATE_GAP AS 
BEGIN
    INSERT INTO DUMMY_DATES 
    SELECT to_date(add_months(date '2015-01-01', level - 1), 'yyyy-mm-dd') mth, 
           'V'
    FROM   DUAL 
    connect by level <= 14
    MINUS
    SELECT DT, 
           FLAG
    FROM   DUMMY_DATES;
END FILL_DATE_GAP;

Я хотел бы сделать то же самое для следующей таблицы:

|----------|----------|----------|
|  EID     |  DT      |  FLAG    |
|----------|----------|----------|
|  123     | 2015-MAY |  E       |
|  123     | 2015-JUN |  H       |
|  123     | 2015-OCT |  E       |
|  123     | 2016-FEB |  E       |
|----------|----------|----------|

Чтобы получить:

|----------|----------|----------|
|  EID     |  DT      |  FLAG    |
|----------|----------|----------|
|  123     | 2015-MAY |  E       |
|  123     | 2015-JUN |  H       |
|  123     | 2015-JUL |  V       |
|  123     | 2015-AUG |  V       |
|  123     | 2015-SEP |  V       |
|  123     | 2015-OCT |  E       |
|  123     | 2015-NOV |  V       |
|  123     | 2015-DEC |  V       |
|  123     | 2016-JAN |  V       |
|  123     | 2016-FEB |  E       |
|----------|----------|----------|

Вопрос Может кто-нибудь сказать мне, как это сделать (тиражирование EID)?

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Если кому-то интересно, получилось так:

        FOR employee_rec IN c_employee
        LOOP
            INSERT INTO XE_GRID_OUTPUT
            SELECT  i_employerId, 
                    employee_rec.EMPLOYEEID,
                    to_date(add_months(date '2014-01-01', level - 1), 'YYYY-MM-DD') mth,
                    'V'
            FROM   DUAL 
            CONNECT BY LEVEL <= 14
            MINUS
            SELECT EMPLOYERID, EMPLOYEEID, DECLARATIONPERIOD, FLAG
            FROM XE_GRID_OUTPUT
            WHERE EMPLOYEEID=employee_rec.EMPLOYEEID;
        END LOOP;

Курсор, выбирающий EMPLOYEEID для данного идентификатора работодателя.

0 голосов
/ 23 мая 2018

То, что вы ищете здесь, это выполнить некоторое уплотнение данных, заполняя пробелы в ваших данных.

Начиная с вашей малонаселенной таблицы, используя многораздельное внешнее соединение с таблицей плотных измерений, вы можете достичьgoal:

With Date_Dim(dt) as (
  select date '2015-05-01'
       + numtoyminterval(level-1,'month')
     from dual 
  connect by level <= 14
)
select t1.eid
     , dd.dt
     , nvl(t1.flag, 'V') flag
  from Date_Dim dd
  left join YourData t1 partition by (t1.EID)
    on t1.dt = dd.dt;

В вышеприведенном коде я определяю выражение общей таблицы Date_Dim (CTE) как измерение с плотной датой и оставляю внешнее соединение его с YourData, разделяя соединение столбцом EID.Одно это гарантирует, что для каждого значения eid будет по крайней мере одна строка для каждого значения DT в таблице Date_Dim.Последний бит должен гарантировать, что ваш столбец флага возвращает 'V' вместо NULL, что просто обрабатывается функцией NVL в проекции запросов.

Вот SQL Fiddle , показывающий его вдействие и выходные данные, сгенерированные вышеуказанным запросом в этой скрипке:

Результаты :

| EID |                   DT | FLAG |
|-----|----------------------|------|
| 123 | 2015-05-01T00:00:00Z |    E |
| 123 | 2015-06-01T00:00:00Z |    H |
| 123 | 2015-07-01T00:00:00Z |    V |
| 123 | 2015-08-01T00:00:00Z |    V |
| 123 | 2015-09-01T00:00:00Z |    V |
| 123 | 2015-10-01T00:00:00Z |    E |
| 123 | 2015-11-01T00:00:00Z |    V |
| 123 | 2015-12-01T00:00:00Z |    V |
| 123 | 2016-01-01T00:00:00Z |    V |
| 123 | 2016-02-01T00:00:00Z |    E |
| 123 | 2016-03-01T00:00:00Z |    V |
| 123 | 2016-04-01T00:00:00Z |    V |
| 123 | 2016-05-01T00:00:00Z |    V |
| 123 | 2016-06-01T00:00:00Z |    V |

Если вы хотите запрос, подходящий длявставив обратно в исходную таблицу только недостающие столбцы EID / Date, вы можете добавить t1.flag в предложение WHERE, равное нулю.

поочередно

Если выкак запрос больше похож на ваш оригинал, вы можете использовать перекрестный продукт для генерации всех строк и минус исходные данные:

With Date_Dim(dt) as (
  select date '2015-05-01'
       + numtoyminterval(level-1,'month')
     from dual 
  connect by level <= 14
)
select t1.eid, dd.dt, 'V'
  from Date_Dim dd
 cross join YourData t1
minus 
select eid, dt, 'V' from YourData
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...