Oracle присоединяется к первой строке подзапроса - PullRequest
4 голосов
/ 09 января 2012

Это может показаться простым, но почему-то это не так.У меня есть таблица исторических данных о ставках, называемая TBL_A, которая выглядит следующим образом:

|   id   |  rate  |  added_date  |
|--------|--------|--------------|
|  bill  |  7.50  |   1/24/2011  |
|  joe   |  8.50  |   5/3/2011   |
|  ted   |  8.50  |   4/17/2011  |
|  bill  |  9.00  |   9/29/2011  |

В TBL_B у меня есть часы, которые необходимо объединить в одну строку TBL_A для получения информации о стоимости:

|   id   |  hours  |  added_date  |
|--------|---------|--------------|
|  bill  |   10    |   2/26/2011  |  
|  ted   |   4     |   7/4/2011   |
|  bill  |   9     |   10/14/2011 |

Как видите, для Билла в TBL_A есть две ставки, но у них разные даты.Чтобы правильно рассчитать стоимость Билла за период времени, вы должны присоединиться к каждой строке TBL_B в строке в TBL_A, которая соответствует дате.

Я подумал, что это будет легко;поскольку для этого не требовался исключительно быстрый запрос, я мог просто сделать отдельный подзапрос для каждой строки информации о стоимости.Однако присоединенные подзапросы, очевидно, не могут «видеть» другие таблицы, к которым они присоединены.Этот запрос выбрасывает недопустимый идентификатор (ORA-00904) для чего-либо в подзапросе с псевдонимом «h»:

SELECT h.id, r.rate * h.hours as "COST", h.added_date
     FROM TBL_B h
     JOIN (SELECT * FROM (
                SELECT i.id, i.rate 
                     FROM TBL_A i 
                WHERE i.id = h.id and i.added_date < h.added_date
                ORDER BY i.added_date DESC)
           WHERE rownum = 1) r
      ON h.id = r.id

Если проблема просто в определении объема, я не знаю, использовал ли я подходможет работатьНо все, что я пытаюсь сделать, это получить одну строку на основе некоторых критериев, поэтому я определенно открыт для других методов.

РЕДАКТИРОВАТЬ: Желаемый результат будет следующим:

|   id   |   cost  |  added_date  |
|--------|---------|--------------|
|  bill  |   75    |   2/26/2011  |  
|  ted   |   34    |   7/4/2011   |
|  bill  |   81    |   10/14/2011 |

Обратите внимание, что у Билла есть две разные ставки в двух записях таблицы.Первый ряд 10 * 7.50 = 75, а второй ряд 9 * 9.00 = 81.

Ответы [ 2 ]

4 голосов
/ 09 января 2012

Попробуйте использовать not exists:

select
    b.id,
    a.rate,
    b.hours,
    a.rate*b.hours as "COST", 
    b.added_date,
    a.added_date
from
    tbl_b b
    inner join tbl_a a on
        b.id = a.id
where
    a.added_date < b.added_date
    and not exists (
        select 
            1 
        from 
            tbl_a a2 
        where 
            a2.added_date > a.added_date 
            and a2.added_date < b.added_date
            and a2.id = a.id 
        )

В качестве объяснения, почему это происходит: только коррелированные подзапросы знают о контексте, в котором они выполняются, поскольку они запускаются для каждой строки,Объединенный подзапрос фактически выполняется до объединения, поэтому он не знает окружающих таблиц.Вам нужно вернуть всю идентифицирующую информацию вместе с ним, чтобы выполнить объединение на верхнем уровне запроса, а не пытаться сделать это внутри подзапроса.

1 голос
/ 09 января 2012
select id, cost, added_date from (
select
  h.id,
  r.rate * h.hours as "COST",
  h.added_date,
  -- For each record, assign r=1 for 'newest' rate
  row_number() over (partition by h.id, h.added_date order by r.added_date desc) r
from
  tbl_b h,
  tbl_a r 
where
  r.id = h.id and
  -- Date of rate must be entered before
  -- hours billed:
  r.added_date < h.added_date
)
where r = 1
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...