2013-07-23 2 views
0

у меня есть две таблицыOracle 11g: Sub запрос возвращения нескольких строк

Таблица-1: Account_Table

Account_Num | Serial_Num | Transaction_Date | Balance | Frequency 
    ACC1   001   Date1   0   f1 
    ACC1   002   Date2   1   f2 
    ACC1   003   Date3   2   f3 

Таблица-2: Bill_Table

Account_Num | Serial_Num | Version_Num | Bill_Date 
    ACC1   001   1   Date1 (say) 
    ACC1   002   1   Date2 
    ACC1   001   1   Date3 

мне нужно получите Bill_Date от Bill_Table, присоединившись к Account_Num и Serial_Num как Account_Table, так и Bill_Table.

Если Bill_Table имеет более одной строки, совпадает с Account_Num, Serial_Num. Это касается ACC1, 001 of Account_Table совпадений с двумя строками ACC1, 001 of Bill_Table, тогда мне нужно получить максимальный номер версии соответствующей комбинации Account_Num, Serial_Num и вернуть Bill_Date этой строки.

Это особый случай, когда номер версии одинакова для обоих ACC1, 001 комбинации, так что мне нужно, чтобы получить TOP 1 (то есть ROWNUM = 1)

Пример: Account_Table имеет 3 строки. Теперь мой вывод должен быть

Ожидаемый результат:

Account_Num | Serial_Num | Bill_Date 
    ACC1   001   Date 
    ACC1   002   Date 
    ACC1   003   null 

запросов, которые я попытался это,

SELECT 
      A.ACCOUNT_NUM, 
      A.SERIAL_NUM, 
      B.BILL_DATE 
    FROM ACCOUNT_TABLE A, BILL_TABLE B WHERE 
     A.ACCOUNT_NUM = 'ACC1' AND 
     B.ACCOUNT_NUM = 'ACC1' AND 
     A.SERIAL_NUM = B.SERIAL_NUM AND  
     B.VERSION_NUM = (SELECT MAX (BIV.VERSION_NUM) FROM BILL_TABLE BIV 
            WHERE BIV.ACCOUNT_NUM = 'ACC1' 
            AND BIV.SERIAL_NUM = B.SERIAL_NUM 
         ); 

Но этот запрос приводит к таблице, которая не показывает мою ACC1, 003 комбинацию и ACC1, 001 2 раза.

ВЫВОД:

ACCOUNT_NUM | SERIAL_NUM | BILL_DATE 
    ACC1   001   Date 
    ACC1   001   Date 
    ACC2   002   Date 

Любая помощь будет оценена.

P.S: Одна вещь, которую я совершил неправильно, я сравниваю только строки, соответствующие как серийным номерам A.SERIAL_NUM = B.SERIAL_NUM. Но если я удалю эту строку, я получаю больше строк.

ответ

3

Это должно сделать то, что вам нужно, используя LEFT JOIN и ROW_NUMBER(), чтобы найти нужную версию;

SELECT account_num, serial_num, version_num, bill_date 
FROM (
    SELECT a.account_num,a.serial_num,b.version_num,b.bill_date, 
    ROW_NUMBER() OVER (PARTITION BY a.account_num, a.serial_num 
         ORDER BY b.version_num DESC) rn 
    FROM account_table a 
    LEFT JOIN bill_table b 
    ON a.account_num = b.account_num 
    AND a.serial_num = b.serial_num 
) 
WHERE rn=1 

An SQLfiddle to test with.

+0

+1 Удивительный. pls дают мне некоторое время для того чтобы испытать с другими случаями. Я уверен, что это сработает. – Amarnath

+0

Интересно! ROW_NUMBER() для меня новичок, так как последний раз я использую oracle в 2010 году. У вас есть мой голос, Йоахим. :) –

+0

Sry моя ошибка .. его работая отлично. – Amarnath

1

Два ряда является случиться, так как таблица Bill_table имеет два ряда с VERSION_NUM = 1 для ACCOUNT_NUM = ACC1 и serial_num = 001.

И ACC3 не показывается, потому что вы не делаете LEFT OUTER JOIN еще.

Ниже приведен запрос:

SELECT A.ACCOUNT_NUM, A.SERIAL_NUM, B.VERSION_NUM, B.BILL_DATE 
FROM ACCOUNT_TABLE A 
LEFT OUTER JOIN 
(
    SELECT ACCOUNT_NUM, SERIAL_NUM, VERSION_NUM, BILL_DATE 
    FROM (
     SELECT ACCOUNT_NUM, SERIAL_NUM, VERSION_NUM, BILL_DATE, 
     MAX(VERSION_NUM) OVER (PARTITION BY ACCOUNT_NUM, SERIAL_NUM) AS MAX_VERSION_NUM, 
     MAX(BILL_DATE) OVER (PARTITION BY ACCOUNT_NUM, SERIAL_NUM, VERSION_NUM) AS MAX_BILL_DATE 
     FROM BILL_TABLE 
    ) WHERE VERSION_NUM = MAX_VERSION_NUM AND BILL_DATE = MAX_BILL_DATE 
) B ON B.ACCOUNT_NUM = A.ACCOUNT_NUM AND B.SERIAL_NUM = A.SERIAL_NUM 

Надеется, что это поможет.

+0

+1 Да. Я также попытался использовать левое внешнее соединение.но все же я не могу получить ожидаемые результаты. – Amarnath

+0

Привет, Che, обновил свой ответ для запроса. –

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