子查询返回多行SQL

时间:2009-08-25 10:49:03

标签: sql tsql subquery

我已经执行了代码

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标识。如果副本可用,它应该只返回'在lib',否则,来自贷款表的duedate。例如,如果一本书有3个副本,2个和1个在lib中,我希望我的查询显示所有三个副本。我想我错过了一个外连接。能否澄清一下。

我用于此的表格是

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

2 个答案:

答案 0 :(得分: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。

罗布

答案 1 :(得分: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子句可能是必要的,也可能没有,你也应该检查一下。这取决于图书编号是否是唯一的,或者是否针对不同的图书重复。