2

我已经执行了一段代码

SELECT CASE b.ON_LOAN
    when 'Y' then
        'In Lib'
    when 'N' then 
        (SELECT c.duedate from book_copy a, book b, loan c
            where b.isbn = 123456
            and a.isbn = b.isbn 
            and a.book_no = c.book_no)
    END AS Availability, a.isbn, a.class_number 
FROM book_copy b, book a
where a.isbn = b.isbn and a.isbn = 123456

它返回一个错误,说子查询返回多于一行。我正在尝试获取一本书的可用性。一本书可以有多个副本,由其 book_no 标识。如果副本可用,则应仅返回“在库中”,否则应返回贷款表中的到期日期。例如,如果一本书有三份,两份出,一份在库中,我希望我的查询显示所有三份。我想我缺少一个外部连接。请你澄清一下。

我用于此的表是

book_copy: book_no, isbn, on_loan
loan: student_id, book_no, duedate,datereturned,loan_id
    fk: book_no with book_no in book_copy
book: isbn (pk), title, class

谢谢, rk

4

2 回答 2

10

问题出在:

(SELECT c.duedate from book_copy a, book b, loan c where b.isbn = 123456 and a.isbn = b.isbn and a.book_no = c.book_no)

您实际上只想要贷款表,但使用 MAX 确保它只返回一行。

(SELECT MAX(c.duedate) from loan c where a.book_no = c.book_no)

所以......您可以挂钩到外部查询中的表 - 无需再次使用 a 和 b 。

于 2009-08-25T10:53:35.573 回答
1

我会首先摆脱那些隐含的连接。然后我会使用派生表而不是相关子查询(永远不要使用相关子查询,它们是性能狗!)

SELECT 
    CASE b.ON_LOAN    
        WHEN 'Y' THEN 'In Lib'    
        WHEN 'N' THEN c.duedate END
        AS Availability, 
    a1.isbn, 
    a.class_number 
FROM book_copy b
JOIN book A1   
    ON a1.isbn = b.isbn 
JOIN (SELECT MIN(c.duedate), c.isbn  FROM loan c 
            join  book a 
            on a.a.isbn = c.isbn            
     WHERE a.isbn = 123456 AND datereturned is null
        GROUP BY  c.isbn 
        ) c 
    ON a1.isbn =  c.isbn 
WHERE a.isbn = 123456       

最初,我使用 max 是因为您没有给我们指示如何在您只需要一条记录时选择贷款表中的哪些记录。但是,我怀疑有更好的方法(或者至少我希望你的设计有更好的方法)来找到这本书。也许您有一个字段表明该书已被归还,或者您可能希望第一本可以归还的书的日期而不是最晚归还的日期。不要在不考虑如何只获得一条记录的情况下使用 max。否则,您可能正在编写一个有效但结果不正确的查询。根据您在下面的评论,我修改了查询。

理解这一点的关键是派生表应该带回尚未返回但应该尽快可用的记录(即它具有最早的截止日期)。如果我的查询没有做到这一点,那么您将需要进行试验,直到找到一个可以做到的。最后的 where 子句可能需要也可能不需要,您也应该检查一下。这取决于书号是唯一的还是不同书的重复。

于 2009-08-26T14:10:45.573 回答