2016-05-03 4 views
0

У меня есть вопрос, как отображать как родительский, так и дочерний: Вот мой пример: T1 является родительским элементом T2.Oracle/SQL - возвращает родительские и дочерние записи

ID  create datetime(mm/dd/yyyy hh:mm:ss) 
1  17-Apr-2016 
2  18-Apr-2016 
3  13-Apr-2016 
4  15-Apr-2016 
5  20-Apr-2016 
6  19-Apr-2016 

ID(FK) seq  create datetime(mm/dd/yyyy hh:mm:ss) 
1  6546  20-Apr-2016 
1  5457  19-Apr-2016 
1  4245  18-Apr-2016 
1  0 
2  5567  19-Apr-2016 
2  0 
3  2034  15-Apr-2016 
3  1987  14-Apr-2016 
3  1902  14-Apr-2016 
3  1249  13-Apr-2016 
3  0 
4  2209  15-Apr-2016 
4  2456  16-Apr-2016 
4  3578  17-Apr-2016 
4  3467  17-Apr-2016 
4  4645  18-Apr-2016 
4  5357  19-Apr-2016 
4  0 
5  0 
6  0 

T2 является дочерним T1, A и B являются текстовые значения, которые я хочу, чтобы отобразить на основе моего состояния, это не исходит из БД. Мое состояние заключено:

  • Если Id не имеет времени на создание в T2/Seq = 0, идентификатор списка в качестве «A». например: 5,6 будет be A
  • Если идентификатор имеет действующее seq/время создания в T2: . затем, получить максимум от createtime Т2
  • Список обе строки - T1 как 'A' и T2 как 'B'

В идеале мой выход будет:

Id createtime Type 
1 17-Apr-2016 A 
1 20-Apr-2016 B 
2 18-Apr-2016 A 
2 19-Apr-2016 B 
3 13-Apr-2016 A 
3 15-Apr-2016 B 
4 15-Apr-2016 A 
4 15-Apr-2016 B 
5 20-Apr-2016 A 
6 19-Apr-2016 A 

редактировать: я также необходимо добавить фильтр даты/времени T1.createdatetime между to_date (01-Apr-2016) и to_date (30-Apr-2016) или T2.createdatetime между to_date (01-Apr-2016) и to_date (30- Apr-2016)

+0

Это, вероятно, НЕ то, что вы хотите; записи, созданные 30 апреля, НЕ будут выбраны, если у них есть компонент времени, отличный от 00:00:00, потому что to_date (30 апреля 2016 года) без показанного времени означает 00:00:00.Я показываю другое соглашение в своем решении. – mathguy

ответ

0

Я думаю, что просто союз должен это сделать:

WITH T1 as(
select 1 ID,  '17-Apr-2016' as crte from dual union all 
select 2 ID,  '18-Apr-2016' as crte from dual union all 
select 3 ID,  '13-Apr-2016' as crte from dual union all 
select 4 ID,  '15-Apr-2016' as crte from dual union all 
select 5 ID,  '20-Apr-2016' as crte from dual union all 
select 6 ID,  '19-Apr-2016' as crte from dual 
) 
, 
T2 as(
select 1 ID,  6546 SEQ,  '20-Apr-2016' as crte from dual union all 
select 1 ID,  5457 SEQ,  '19-Apr-2016' as crte from dual union all 
select 1 ID,  4245 SEQ,  '18-Apr-2016' as crte from dual union all 
select 1 ID,  0 SEQ,   NULL as crte from dual union all 
select 2 ID,  5567 SEQ,  '19-Apr-2016' as crte from dual union all 
select 2 ID,  0 SEQ,   NULL as crte from dual union all 
select 3 ID,  2034 SEQ,  '15-Apr-2016' as crte from dual union all 
select 3 ID,  1987 SEQ,  '14-Apr-2016' as crte from dual union all 
select 3 ID,  1902 SEQ,  '14-Apr-2016' as crte from dual union all 
select 3 ID,  1249 SEQ,  '13-Apr-2016' as crte from dual union all 
select 3 ID,  0 SEQ,   NULL as crte from dual union all 
select 4 ID,  2209 SEQ,  '15-Apr-2016' as crte from dual union all 
select 4 ID,  2456 SEQ,  '16-Apr-2016' as crte from dual union all 
select 4 ID,  3578 SEQ,  '17-Apr-2016' as crte from dual union all 
select 4 ID,  3467 SEQ,  '17-Apr-2016' as crte from dual union all 
select 4 ID,  4645 SEQ,  '18-Apr-2016' as crte from dual union all 
select 4 ID,  5357 SEQ,  '19-Apr-2016' as crte from dual union all 
select 4 ID,  0 SEQ,   NULL as crte from dual union all 
select 5 ID,  0 SEQ,   NULL as crte from dual union all 
select 6 ID,  0 SEQ,   NULL as crte from dual 
) 

select ID, crte, 'A' Type from T1 where crte between to_date('01-Apr-2016') and to_date('30-Apr-2016') 
union 
select ID, max(crte), 'B' Type from T2 where seq <> 0 and crte between to_date('01-Apr-2016') and to_date('30-Apr-2016') group by ID; 

ВЫВОД:

 ID CRTE  TYPE 
---------- ----------- ---- 
     1 17-Apr-2016 A  
     1 20-Apr-2016 B  
     2 18-Apr-2016 A  
     2 19-Apr-2016 B  
     3 13-Apr-2016 A  
     3 15-Apr-2016 B  
     4 15-Apr-2016 A  
     4 19-Apr-2016 B  
     5 20-Apr-2016 A  
     6 19-Apr-2016 A  
+0

Это может не работать, если идентификатор не имеет строки с SEQ = 0 в T2; ваш запрос вернет create_date из T1 независимо. (Возможно, это то, чего действительно хочет ОП - или, возможно, ВСЕ-ИД имеют строку с SEQ = 0 в T1, но это не то, что ОП описал в исходном вопросе.) Добавленные условия будут ** не ** выбирать записи, созданные на 30-апр-2016 с разницей с 00:00:00. – mathguy

+0

@mathguy yea desc был немного расплывчатым, но я просто основывал его на идеальном выводе OP. Я думаю, что hes также получил неверную максимальную дату для ID 4 в своем выпуске. Но одно из этих решений должно покрыть его для него – mo2

0

Что-то вроде этого ... Обратите внимание, что я изменил входные данные так, что она охватывает все возможные комбинации (я думаю).

with t1 (id, create_datetime) as 
     (select 1, date '2016-04-17' from dual union all 
      select 2, date '2016-04-18' from dual union all 
      select 3, date '2016-04-10' from dual 
     ), 
    t2 (id, seq, create_datetime) as 
     (
      select 1, 6546, date '2016-04-20' from dual union all 
      select 1, 5457, date '2016-04-19' from dual union all 
      select 1, 4245, date '2016-04-18' from dual union all 
      select 1, 0 , null    from dual union all 
      select 2, 5567, date '2016-04-19' from dual union all 
      select 2, 4003, date '2016-04-21' from dual union all 
      select 3, 0 , null    from dual 
     ) 
select t1.id, t1.create_datetime, 'A' as type 
    from t1 join t2 on t1.id = t2.id 
    where t2.seq = 0 
    and t1.create_datetime >= date '2016-04-01' 
    and t1.create_datetime < date '2016-05-01' 
union all 
select id, max(create_datetime), 'B' 
    from t2 
    where create_datetime >= date '2016-04-01' 
    and create_datetime < date '2016-05-01' 
    group by id 
order by id, type; 

Output (с данными t1 и t2, определенных в С п):

 ID CREATE_DATE TYPE 
---------- ----------- ---- 
     1 17-Apr-2016 A 
     1 20-Apr-2016 B 
     2 21-Apr-2016 B 
     3 10-Apr-2016 A 
0

Вы можете сделать это без союза и с использованием только одного сканирования таблицы на каждой таблицы:

Настройка

Oracle:

CREATE TABLE T1 (ID, CRTE) AS 
select 1, DATE '2016-04-17' FROM DUAL UNION ALL 
select 2, DATE '2016-04-18' FROM DUAL UNION ALL 
select 3, DATE '2016-04-13' FROM DUAL UNION ALL 
select 4, DATE '2016-04-15' FROM DUAL UNION ALL 
select 5, DATE '2016-04-20' FROM DUAL UNION ALL 
select 6, DATE '2016-04-19' FROM DUAL; 

CREATE TABLE T2 (ID, SEQ, CRTE) AS 
select 1, 6546, DATE '2016-04-20' FROM DUAL UNION ALL 
select 1, 5457, DATE '2016-04-19' FROM DUAL UNION ALL 
select 1, 4245, DATE '2016-04-18' FROM DUAL UNION ALL 
select 1, 0, NULL    FROM DUAL UNION ALL 
select 2, 5567, DATE '2016-04-19' FROM DUAL UNION ALL 
select 2, 0, NULL    FROM DUAL UNION ALL 
select 3, 2034, DATE '2016-04-15' FROM DUAL UNION ALL 
select 3, 1987, DATE '2016-04-14' FROM DUAL UNION ALL 
select 3, 1902, DATE '2016-04-14' FROM DUAL UNION ALL 
select 3, 1249, DATE '2016-04-13' FROM DUAL UNION ALL 
select 3, 0, NULL    FROM DUAL UNION ALL 
select 4, 2209, DATE '2016-04-15' FROM DUAL UNION ALL 
select 4, 2456, DATE '2016-04-16' FROM DUAL UNION ALL 
select 4, 3578, DATE '2016-04-17' FROM DUAL UNION ALL 
select 4, 3467, DATE '2016-04-17' FROM DUAL UNION ALL 
select 4, 4645, DATE '2016-04-18' FROM DUAL UNION ALL 
select 4, 5357, DATE '2016-04-19' FROM DUAL UNION ALL 
select 4, 0, NULL    FROM DUAL UNION ALL 
select 5, 0, NULL    FROM DUAL UNION ALL 
select 6, 0, NULL    FROM DUAL; 

Запрос:

SELECT T1.id, 
     COALESCE(T2.CRTE, T1.CRTE) AS CRTE, 
     CASE SEQ WHEN 0 THEN 'A' ELSE 'B' END AS Type 
FROM T1 
     INNER JOIN 
     (SELECT t.*, 
       CASE SEQ WHEN 0 THEN 1 
        ELSE ROW_NUMBER() OVER (PARTITION BY ID 
               ORDER BY CRTE DESC 
               NULLS LAST) 
        END AS RN 
     FROM T2 t) T2 
     ON (t1.ID = t2.ID AND t2.RN = 1) 
ORDER BY id, type; 

Выход:

 ID CRTE    TYPE 
---------- ------------------- ---- 
     1 2016-04-17 00:00:00 A  
     1 2016-04-20 00:00:00 B  
     2 2016-04-18 00:00:00 A  
     2 2016-04-19 00:00:00 B  
     3 2016-04-13 00:00:00 A  
     3 2016-04-15 00:00:00 B  
     4 2016-04-15 00:00:00 A  
     4 2016-04-19 00:00:00 B  
     5 2016-04-20 00:00:00 A  
     6 2016-04-19 00:00:00 A 

Запрос 2 - С помощью фильтров:

SELECT T1.id, 
     COALESCE(T2.create_datetime, T1.create_datetime) AS create_datetime, 
     CASE SEQ WHEN 0 THEN 'A' ELSE 'B' END AS Type 
FROM T1 
     INNER JOIN 
     (SELECT T2.*, 
       CASE SEQ WHEN 0 THEN 1 
        ELSE ROW_NUMBER() OVER (PARTITION BY ID 
               ORDER BY create_datetime DESC 
               NULLS LAST) 
        END AS RN 
     FROM T2 
     WHERE create_datetime IS NULL 
     OR  create_datetime BETWEEN DATE '2016-04-01'AND DATE '2016-04-30' 
     ) T2 
     ON (t1.ID = t2.ID AND t2.RN = 1) 
WHERE T1.create_datetime BETWEEN DATE '2016-04-01'AND DATE '2016-04-30' 
ORDER BY id, type; 

Выход:

 ID CREATE_DATETIME  TYPE 
---------- ------------------- ---- 
     1 2016-04-17 00:00:00 A  
     1 2016-04-20 00:00:00 B  
     2 2016-04-18 00:00:00 A  
     2 2016-04-19 00:00:00 B  
     3 2016-04-13 00:00:00 A  
     3 2016-04-15 00:00:00 B  
     4 2016-04-15 00:00:00 A  
     4 2016-04-19 00:00:00 B  
     5 2016-04-20 00:00:00 A  
     6 2016-04-19 00:00:00 A  
Смежные вопросы