2013-12-04 2 views
0

Так что у меня проблема с вложенным выбором, который я пытаюсь сделать в таблице данных.Предложение WHERE во вложенном select

У меня есть ряд книг по нескольким библиотекам. Каждая книга имеет идентификатор, а в каждом месте - имя. Каждый раз, когда книга вынимается или возвращается, транзакция записывается в таблицу транзакций.

таблица выглядит немного как это:

+---------+--------+----------+------------+ 
| BOOK_ID | IN_OUT | LOCATION | DATE | 
+---------+--------+----------+------------+ 
| B01  | O  | RED  | 2013-10-04 | 
| B02  | O  | BLUE  | 2013-10-04 | 
| B01  | I  | RED  | 2013-10-19 | 
| B01  | O  | RED  | 2013-10-20 | 
| B02  | I  | RED  | 2013-10-21 | 
| B01  | I  | BLUE  | 2013-10-24 | 
+---------+--------+----------+------------+ 

(Спасибо, @Senseful!)

Прямо сейчас, я могу показать все операции и их IN_time, OUT_time отображенные в парах:

SELECT i.BOOK_ID 
        ,(SELECT MAX(o.DATE) 
         FROM TRANSACTIONS o 
        WHERE (o.IN_OUT = 'O') 
         AND o.BOOK_ID = i.BOOK_ID 
         AND o.DATE < i.DATE 
       ) AS out_time 
    , i.DATE AS in_time 
    , LOCATION 
    FROM TRANSACTIONS i 
WHERE i.IN_OUT = 'I' 
ORDER BY i.DATE 
; 

Теперь, однако, я хочу показывать только транзакции, когда книги возвращаются в другое место: так, в приведенном выше примере, я попытался выбрать LOCATION as ou t_location с намерением добавить предложение WHERE, чтобы проверить, равно ли оно in_location.

Справедливо:

,(SELECT MAX(o.DATE), LOCATION as out_location 
         FROM TRANSACTIONS o 

Нет может сделать. "ORA-00913: too many values".

Любые идеи относительно того, что было бы самым разумным способом ограничения вывода, подобного этому?

+0

Вы можете получить результаты, используя analyitic функции. Проверьте этот вопрос на примере: http://stackoverflow.com/questions/17824432/oracle-analytic-functions-resetting-a-windowing-clause –

+0

Вы можете добавить 'AND o.location <> i.location' в свой внутренний выберите, но это не даст вам текущее местоположение книги. – SQB

+0

@SQB Правильно, это выглядит немного более перспективным ... оценивает правильно, давая мне '(null)' на 'out_time', как и ожидалось. Добавление 'where ... out_time не null 'на внешний выбор, хотя дает' ORA-00904: «i». «Out_time»: недопустимый идентификатор' - не «видит» этот столбец out_time? – Ron

ответ

1

Аналитические функции отлично подходят для такого рода запросов. Вы можете использовать LEAD или LAG, чтобы получить предыдущую или следующую строку в группе.

Я создал SQLFiddle пример для вас: http://www.sqlfiddle.com/#!4/725c1/14

В результате оператор выбора заключается в следующем:

select * 
from (
    SELECT i.BOOK_ID 
    , i.in_out 
    , i.event_date AS in_time 
    , LOCATION in_location 
    , lag(event_date) over (partition by book_id order by event_date) out_date 
    , lag(location) over (partition by book_id order by event_date) out_location 
    FROM TRANSACTIONS i 
    ORDER BY i.event_date) 
where in_out = 'I' 
and in_location != out_location; 
+0

Amazing. Теперь у меня есть еще кое-что, о чем нужно читать ... аналитические функции! Спасибо, @Alen. – Ron

+1

Это я возвращаюсь, чтобы еще раз поблагодарить вас. Я просто использовал его в другом контексте, полностью заменив бегемота заявления, которое у меня было. Это прекрасно. Я чувствую себя новым человеком. Жизнь хороша. – Ron

+0

Он он, я рад, что тебе это нравится. –

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