嵌套select中的WHERE子句

时间:2013-12-04 11:39:40

标签: sql oracle

所以我在一个嵌套选择上遇到了一些问题,我试图在数据表上做。

我有很多图书馆的书籍。每本书都有一个ID,每个位置都有一个名称。每次取出或退回书籍时,交易都会记录在交易表中。

表格看起来有点像这样:

+---------+--------+----------+------------+
| 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作为out_location,目的是添加一个WHERE子句来检查是否它等于in_location。

足够公平:

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

没有办法。 “ORA-00913: too many values”。

关于限制输出的最合理方式的任何想法都是这样的吗?

1 个答案:

答案 0 :(得分:1)

分析函数非常适合此类查询。您可以使用LEADLAG来获取组中的上一行或下一行。

我为您创建了一个SQLFiddle示例:http://www.sqlfiddle.com/#!4/725c1/14

生成的select语句是:

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;