2011-01-18 2 views
3

Я хотел бы вернуть первую строку только из внутреннего соединения. У меня две таблицы:Возврат одной строки на INNER JOIN

Строки в TABLE_D и TABLE_E могут иметь идентичные даты создания, поэтому я сначала получаю MAX (createdate), а затем MAX (id) из этого набора. Вот мой полный запрос:

 
SELECT 
a.id as A_ID, 
b.id as B_ID, 
c.id as C_ID, 
d.id as D_ID, 
e.id as E_ID, 
d.CREATIONDATE, 
a.REFNUMBER, 
a.DATECREATED, 
a.INFO, 
e.COST, 
FROM 
TABLE_A a 
INNER JOIN TABLE_B b ON (b.id = a.id) 
INNER JOIN TABLE_C c ON (c.id = b.id) 
INNER JOIN TABLE_D d ON 
(
    c.i = 
    (
     select 
     d.id 
     FROM TABLE_D 
     WHERE TABLE_D.id = c.id 
     AND TABLE_D.id = 
     (
     select 
     max(id) 
     from TABLE_D t1 
     where c_id = c.id 
     and CREATIONDATE = 
     (
      select 
      max(CREATIONDATE) 
      from TABLE_D t2 
      where t2.c_id = t1.c_id 
     ) 
    ) 
    ) 
) 

INNER JOIN TABLE_E e ON 
(
    d.i = 
    (
     select 
     e.d_id 
     from TABLE_E 
     where d_id = d.id 
     AND id = 
     (
     select 
     max(id) 
     from e t1 
     where e.d_id = d.id 
     and CREATIONDATE = 
     (
      select 
      max(CREATIONDATE) 
      from TABLE_E t2 
      where t2.d_id = t1.d_id 
     ) 
    ) 
    ) 
) 


Мой подзапрос, чтобы получить все строки с максимальной CreationDate и от макс ID отлично работает, когда я называю его по себе, но когда я добавляю его в INNER JOIN (см выше) Я получаю строку для каждой соответствующей строки в таблице D и таблице E. То, что я хочу, это одна строка на TABLE_A.id, показывающая только последнюю строку из TABLE_D, связанную с TABLE_C, и последнюю из TABLE_E, связанную с TABLE_D.

Например, идентификаторы в моем наборе результатов выглядеть на данный момент:

 
-------------------------------------------------------------------------- 
A_ID   B_ID   C_ID   D_ID   E_ID 
-------------------------------------------------------------------------- 
1    101    201    301    401 
1    101    201    301    402  
1    101    201    301    403  
1    101    201    302    404 
1    101    201    302    405  
1    101    201    302    406  

, что мне нужно это:

 
-------------------------------------------------------------------------- 
A_ID   B_ID   C_ID   D_ID   E_ID 
-------------------------------------------------------------------------- 
1    101    201    302    406 


Заранее спасибо за вашу помощь.

ответ

1

Используйте аналитическую функцию ROW_NUMBER(), которая доступна в oracle11g

SELECT * 
FROM 
(
SELECT 
    a.id as A_ID,b.id as B_ID,c.id as C_ID,d.id as D_ID,e.id as E_ID, 
    d.CREATIONDATE,a.REFNUMBER,a.DATECREATED,a.INFO,e.COST, 
    row_number() over (
     partition by a.id, b.id, c.id 
     order by d.CREATIONDATE DESC, d.id desc, e.CREATIONDATE DESC, e.id desc) RN 
FROM TABLE_A a 
INNER JOIN TABLE_B b ON (b.id = a.id) 
INNER JOIN TABLE_C c ON (c.id = b.id) 
INNER JOIN TABLE_D d ON d.c_id = c.id 
INNER JOIN TABLE_E e ON e.d_id = d.id 
) N 
WHERE RN = 1 

Просто убедитесь, что PARTITION и ORDER BY пунктами являются правильными

partition by a.id, b.id, c.id 
    => start numbering from 1 again when any one of these changes 
order by d.CREATIONDATE DESC, d.id desc, e.CREATIONDATE DESC, e.id desc) 
    => number the rows in this order 
0

Вы можете вставить свой запрос в подзапрос и используйте фильтр WHERE ROWNUM < 2.

SELECT * FROM 
(/* Your SQL */) 
WHERE ROWNUM < 2 
+0

К сожалению, это не будет работать, как мне нужна строка за A_ID. Я просто поместил один результат в свой пример, чтобы показать, что мне нужен последний D_ID и E_ID для каждого A_ID. Спасибо хоть. – adamdunne

1

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

SELECT 
a.id as A_ID, 
b.id as B_ID, 
c.id as C_ID, 
(select max(d.id) from d where d.id =c.id) as d_id) 
FROM 
TABLE_A a 
INNER JOIN TABLE_B b ON (b.id = a.id) 
INNER JOIN TABLE_C c ON (c.id = b.id) 
-1

Возможно, это сработает для вас?

 
SELECT TOP 1 
a.id as A_ID, 
b.id as B_ID, 
c.id as C_ID, 
d.id as D_ID, 
e.id as E_ID, 
d.CREATIONDATE, 
a.REFNUMBER, 
a.DATECREATED, 
a.INFO, 
e.COST, 
FROM 
TABLE_A a 
INNER JOIN TABLE_B b ON (b.id = a.id) 
INNER JOIN TABLE_C c ON (c.id = b.id) 
INNER JOIN TABLE_D d ON (c.i = d.id) 
INNER JOIN TABLE_E e ON (d.i = e.id) 
ORDER BY d.creationdate DESC, e.creationdate DESC 
+0

SELECT TOP 1 не может использоваться в Oracle – Lunc

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