2015-11-05 3 views
2

Мне нужна помощь для решения этой конкретной проблемы sql, я не могу написать хранимые procs, поскольку мне нужно передать это в Hive.Второе самое низкое значение из другой таблицы после присоединения

Есть два tQCles Contr и Lvl, и мне нужно, чтобы они присоединились к ним и заполнили нулевые значения из LVL в объединенном tQCle со значениями из предыдущей строки. У меня есть образцы tQCles в

Contr 
|  id |  EFF_DT | M_NBR | ACTY_SEQ_NBR | L_CD | 
|---------|------------|-------|--------------|------| 
| QQFAE46 | 2000-12-24 | 11 |   1 | POT | 
| QQFAE46 | 2000-12-24 | 11 |   2 | POT | 
| QQFAE46 | 2000-12-24 | 11 |   3 | POT | 
| QCC5433 | 2013-04-21 | 00 |   1 | MIC | 
| QCC5433 | 2013-04-21 | 00 |   2 | MIC | 
| QCC614E | 2015-07-18 | 00 |   1 | MIC | 
| QCC614E | 2015-07-18 | 00 |   4 | MIC | 
| QC56DDF | 1999-10-01 | 14 |   2 | POT | 
| QC56DDF | 1999-10-01 | 14 |   3 | POT | 
| QC56DDF | 1999-10-01 | 14 |   4 | POT | 
| ACB3DC2 | 1999-10-01 | 14 |   1 | POT | 

LVL 
|  id |  EFF_DT | M_NBR | ACTY_SEQ_NBR | OCCR | 
|---------|------------|-------|--------------|------| 
| QQFAE46 | 2000-12-24 | 11 |   1 | 100 | 
| QQFAE46 | 2000-12-24 | 11 |   3 | 100 | 
| QCC5433 | 2013-04-21 | 00 |   2 | 200 | 
| QCC614E | 2015-07-18 | 00 |   3 | 200 | 
| QC56DDF | 1999-10-01 | 14 |   1 | 0 | 

LEFT JOIn of Contr and Lvl 

|  id |  EFF_DT | M_NBR | ACTY_SEQ_NBR | L_CD |  id |  EFF_DT | M_NBR | ACTY_SEQ_NBR | OCCR | 
|---------|------------|-------|--------------|------|---------|------------|--------|--------------|--------| 
| QQFAE46 | 2000-12-24 | 11 |   1 | POT | QQFAE46 | 2000-12-24 |  11 |   1 | 100 | 
| QQFAE46 | 2000-12-24 | 11 |   2 | POT | (null) |  (null) | (null) |  (null) | (null) | 
| QQFAE46 | 2000-12-24 | 11 |   3 | POT | QQFAE46 | 2000-12-24 |  11 |   3 | 100 | 
| QCC5433 | 2013-04-21 | 00 |   1 | MIC | (null) |  (null) | (null) |  (null) | (null) | 
| QCC5433 | 2013-04-21 | 00 |   2 | MIC | QCC5433 | 2013-04-21 |  00 |   2 | 200 | 
| QCC614E | 2015-07-18 | 00 |   1 | MIC | (null) |  (null) | (null) |  (null) | (null) | 
| QCC614E | 2015-07-18 | 00 |   4 | MIC | (null) |  (null) | (null) |  (null) | (null) | 
| QC56DDF | 1999-10-01 | 14 |   2 | POT | (null) |  (null) | (null) |  (null) | (null) | 
| QC56DDF | 1999-10-01 | 14 |   3 | POT | (null) |  (null) | (null) |  (null) | (null) | 
| QC56DDF | 1999-10-01 | 14 |   4 | POT | (null) |  (null) | (null) |  (null) | (null) | 
| ACB3DC2 | 1999-10-01 | 14 |   1 | POT | (null) |  (null) | (null) |  (null) | (null) | 

Теперь мне нужно заполнить значения для пустого ACTY_SEQ_NBR из LvL tQCle со значениями. Критерии: найдите соответствующий ACTY_SEQ_NBR из CONTR (например, из столбца 4 объединенного tQCle) и найдите ACTY_SEQ_NBR из LVL, где ACTY_SEQ_NBR меньше , чем или равно значению от CONTR ACTY_SEQ_NBR для тех же идентификаторов, eff_dt и m_nbr.

для. например, строка №2 имеет нулевое значение ACTY_SEQ_NBR. Соответствует Contr ACTY_SEQ_NBR 2, значение ACTY_SEQ_NBR, которое меньше 2 из LVL, равно 1.

Таким образом, мой идеальный выход должен быть похож на эту строку.

|  id |  EFF_DT | M_NBR | ACTY_SEQ_NBR | L_CD |  id |  EFF_DT | M_NBR | ACTY_SEQ_NBR | OCCR | 
|---------|------------|-------|--------------|------|---------|------------|--------|--------------|--------| 
| QQFAE46 | 2000-12-24 | 11 |   1 | POT | QQFAE46 | 2000-12-24 |  11 |   1 | 100 | 
| QQFAE46 | 2000-12-24 | 11 |   2 | POT | (null) |  (null) | (null) |   1 | (null) | 

I tried a lag query but its not giving correct output for all values. 

Я выполнил запрос Amniders, и я изменил результаты, чтобы получить ожидаемые значения. Вот мои ожидаемые значения

|  ID |  EFF_DT | M_NBR | ACTY_SEQ_NBR | L_CD | LVL_ID | LVL_EFF_DT | LVL_M_NBR | LVL_ACTY_SEQ_NBR | OCCR | CALC_LVL_ACTY_SEQ_NBR | 
|---------|------------|-------|--------------|------|---------|------------|-----------|------------------|--------|-----------------------| 
| QQFAE46 | 2000-12-24 | 11 |   1 | POT | QQFAE46 | 2000-12-24 |  11 |    1 | 100 |      1 | 
| QQFAE46 | 2000-12-24 | 11 |   2 | POT | (null) |  (null) | (null) |   (null) | (null) |      1 | 
| QQFAE46 | 2000-12-24 | 11 |   3 | POT | QQFAE46 | 2000-12-24 |  11 |    3 | 100 |      3 | 
| QC56DDF | 1999-10-01 | 14 |   2 | POT | (null) |  (null) | (null) |   (null) | (null) |      1 | 
| QC56DDF | 1999-10-01 | 14 |   3 | POT | (null) |  (null) | (null) |   (null) | (null) |      1 | 
| QC56DDF | 1999-10-01 | 14 |   4 | POT | (null) |  (null) | (null) |   (null) | (null) |      1 | 
| QCC5433 | 2013-04-21 | 00 |   1 | MIC | (null) |  (null) | (null) |   (null) | (null) |     -99 | 
| QCC5433 | 2013-04-21 | 00 |   2 | MIC | QCC5433 | 2013-04-21 |  00 |    2 | 200 |      2 | 
| QCC614E | 2015-07-18 | 00 |   1 | MIC | (null) |  (null) | (null) |   (null) | (null) |     -99 | 
| QCC614E | 2015-07-18 | 00 |   4 | MIC | (null) |  (null) | (null) |   (null) | (null) |      3 | 
| ACB3DC2 | 1999-10-01 | 14 |   1 | POT | (null) |  (null) | (null) |   (null) | (null) |     -99 | 

Любая помощь приветствуется

ответ

1

Спасибо за более обширные примеры! Это может быть выполнено с одним полным внешним соединением, но я думаю, что агрегация и фильтрация станут беспорядочными. Простейшее ставка слева присоединиться к дважды лвл, первым, чтобы найти «предыдущий act_seq_nbr», а затем снова, как вы были (но с использованием сливаться использовать «предыдущий act_seq_nbr», когда нет act_seq_nbr не найден):

SELECT c.id,c.eff_dt,c.m_nbr,c.acty_seq_nbr, 
     l.id,l.eff_dt,l.m_nbr, 
     coalesce(l.acty_seq_nbr, prev_acty_seq_nbr, -99) l_acty_seq_nbr 
from 
    (  
    select c.id,c.eff_dt,c.m_nbr,c.acty_seq_nbr, 
      MAX(L.acty_seq_nbr) prev_acty_seq_nbr 
    from contr c 
    left join lvl l 
     on 
      c.id=l.id 
      and c.eff_dt=l.eff_dt 
      and c.m_nbr=l.m_nbr 
      and c.acty_seq_nbr>l.acty_seq_nbr 
    GROUP BY 
     c.id,c.eff_dt,c.m_nbr,c.acty_seq_nbr 
    ) c 
left join lvl l 
    on 
     c.id=l.id 
     and c.eff_dt=l.eff_dt 
     and c.m_nbr=l.m_nbr  
     and c.acty_seq_nbr=l.acty_seq_nbr; 

Fiddle: http://www.sqlfiddle.com/#!6/1270f/74/0

Результаты:

|  id |  eff_dt | m_nbr | acty_seq_nbr |  id |  eff_dt | m_nbr | l_acty_seq_nbr | 
|---------|------------|-------|--------------|---------|------------|--------|----------------| 
| AAFAE46 | 2000-12-24 | 11 |   1 | AAFAE46 | 2000-12-24 |  11 |    1 | 
| AAFAE46 | 2000-12-24 | 11 |   2 | (null) |  (null) | (null) |    1 | 
| AAFAE46 | 2000-12-24 | 11 |   3 | AAFAE46 | 2000-12-24 |  11 |    3 | 
| AB56DDF | 1999-10-01 | 14 |   2 | (null) |  (null) | (null) |    1 | 
| AB56DDF | 1999-10-01 | 14 |   3 | (null) |  (null) | (null) |    1 | 
| AB56DDF | 1999-10-01 | 14 |   4 | (null) |  (null) | (null) |    1 | 
| ABC5433 | 2013-04-21 | 00 |   1 | (null) |  (null) | (null) |   -99 | 
| ABC5433 | 2013-04-21 | 00 |   2 | ABC5433 | 2013-04-21 |  00 |    2 | 
| ABC614E | 2015-07-18 | 00 |   1 | (null) |  (null) | (null) |   -99 | 
| ABC614E | 2015-07-18 | 00 |   4 | (null) |  (null) | (null) |    3 | 
| ACB3DC2 | 1999-10-01 | 14 |   1 | (null) |  (null) | (null) |   -99 |    
+0

Спасибо за попытку, но запрос работает не так, как ожидалось. MAX не тот, который мне нужен, если значение theACTY_SEQ объединения таблицы LVL равно null, найдите значение ACTY_SEQ из таблицы LVL, которое меньше значения ACTY_SEQ соответствующей таблицы CONTR. – Abhi

+1

Я с Amninder - можете ли вы предоставить исходный вопрос с образцами данных, которые на самом деле демонстрируют все варианты (и желаемые результаты каждого из них)? – KevinKirkpatrick

0

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

SELECT 
ID, EFF_DT, M_NBR, ACTY_SEQ_NBR, L_CD, LVL_ID, LVL_EFF_DT, LVL_M_NBR, LVL_ACTY_SEQ_NBR, OCCR 
--,LAG(ACTY_SEQ_NMBR) OVER (PARTITION BY ID, EFF_DT, M_NBR ORDER BY ACTY_SEQ_NMBR) 
,COALESCE(CASE WHEN LVL_ACTY_SEQ_NBR IS NULL THEN LAG(ACTY_SEQ_NBR) OVER (PARTITION BY ID, EFF_DT, M_NBR ORDER BY ACTY_SEQ_NBR) ELSE LVL_ACTY_SEQ_NBR END,'NA') CALC_LVL_ACTY_SEQ_NBR FROM(
SELECT A.ID, A.EFF_DT, A.M_NBR, A.ACTY_SEQ_NBR, A.L_CD 
, B.ID LVL_ID, B.EFF_DT LVL_EFF_DT, B.M_NBR LVL_M_NBR, B.ACTY_SEQ_NBR LVL_ACTY_SEQ_NBR , B.OCCR 
FROM EDWT.CONTR A 
LEFT JOIN EDWT.LVL B 
ON A.ID = B.ID AND A.ACTY_SEQ_NBR = B.ACTY_SEQ_NBR and a.eff_dt=b.eff_dt and a.m_nbr=b.m_nbr) A; 
+0

Поблагодарите Amninder за попытку, но не получив ожидаемых результатов. Запрос не работает в случае строки №4 ABC5433 | 2013-04-21 | 00 | 1, где данные LVL являются нулевыми, нам нужно найти самый низкий ACTY_SEQ из LVL. w.r.t до значения, меньшего или равного его значению CONTR. По запросу он возвращает «NA», хотя у нас есть запись в LVL. AB56DDF | 1999-10-01 | 14 | 1 – Abhi

0

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

В то же время, вот трещина на него:

with foo as (
    select 
    c.id as cid, c.eff_dt as c_eff_dt, 
    c.m_nbr as c_m_nbr, c.acty_seq_nbr as c_acty_seq_nbr, 
    l.id as lid, l.eff_dt as l_eff_dt, l.m_nbr as l_m_nbr, 
    l.acty_seq_nbr as l_acty_seq_nbr, 
    sum (case when l.id is null then 0 else 1 end) 
     over (partition by c.id order by c.acty_seq_nbr) as idx 
    from 
    contr c 
    left join lvl l on 
     c.id=l.id and 
     c.eff_dt=l.eff_dt and 
     c.m_nbr=l.m_nbr and 
     c.acty_seq_nbr=l.acty_seq_nbr 
) 
select 
    cid, c_eff_dt, c_m_nbr, c_acty_seq_nbr, 
    lid, l_eff_dt, l_m_nbr, l_acty_seq_nbr, 
    min (c_acty_seq_nbr) over (partition by cid, idx) as acty_seq_nbr 
from foo 
+0

Спасибо Hambone. Я объясню немного больше. После того, как мы введем LEFT в Contr c и LVL l, мы получим нулевые значения для l.id, l.eff_dt, l.m_nbr и l.seq_nbr. Для всех строк, имеющих нуль для LVL l, нам нужно заполнить l.acty_seq_nbr значения из таблицы LVL. Для этого условие - найти a.id, a.eff_dt, a.m_nbr из таблицы Left Left и для значения a.acty_seq_nbr найти меньшее или равное значение из таблицы LV, например (SELECT nl.acty_seq_nbr из LVL nl, где a.id = nl.id и a.eff_dt = nl.eff_dt и a.m_nbr = nl.m_nbr и nl.acty_seq_nbr <= a.acty_seq_nbr). Надеюсь это поможет – Abhi

1

Попробуйте это:

SELECT 
    ID, EFF_DT, M_NBR, ACTY_SEQ_NBR, L_CD, LVL_ID, LVL_EFF_DT, LVL_M_NBR, LVL_ACTY_SEQ_NBR, OCCR 
    ,COALESCE(CASE WHEN LVL_ACTY_SEQ_NBR IS NULL THEN COALESCE(LAG(ACTY_SEQ_NBR) OVER (PARTITION BY ID, EFF_DT, M_NBR ORDER BY ACTY_SEQ_NBR),ACTY_SEQ_NBR) ELSE LVL_ACTY_SEQ_NBR END,'NA') LVL_NMBR 
    FROM(
    SELECT A.ID, A.EFF_DT, A.M_NBR, A.ACTY_SEQ_NBR, A.L_CD 
    , B.ID LVL_ID, B.EFF_DT LVL_EFF_DT, B.M_NBR LVL_M_NBR, B.ACTY_SEQ_NBR LVL_ACTY_SEQ_NBR , B.OCCR 
    FROM EDWT.CONTR A 
    LEFT JOIN EDWT.LVL B 
    ON A.ID = B.ID AND A.ACTY_SEQ_NBR = B.ACTY_SEQ_NBR and a.eff_dt=b.eff_dt and a.m_nbr=b.m_nbr) A; 

Кроме того, пожалуйста, помогите с допустимым значением для следующих строк:

ID EFF_DT M_NBR ACTY_SEQ_NBR L_CD LVL_ID LVL_EFF_DT LVL_M_NBR LVL_ACTY_SEQ_NBR OCCR LVL_NMBR

ABC5433 2013-04-21 00 1 IMC 1

какие данные вы ожидаете для lvl_acty_seq_nbr для ABC614E & ABC5433. ABC614E не имеет acty_Seq_nbr в таблице lvl и имеет 1 & 4in contr. Укажите ожидаемый результат для указанного выше идентификатора. Вы хотите получить самое низкое значение в пределах одного и того же идентификатора или самого низкого значения из всех идентификаторов?

Смежные вопросы