Подзапрос возвращает более одной строки SQL - PullRequest
2 голосов
/ 25 августа 2009

Я выполнил код

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. Если копия доступна, она должна перезапускаться просто «В библиотеке», в противном случае - из таблицы ссуд. Например, если у книги три копии, 2 из 1 и 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

спасибо, гк

Ответы [ 2 ]

10 голосов
/ 25 августа 2009

Проблема в:

(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.

Rob

1 голос
/ 26 августа 2009

Я бы сначала избавился от этих подразумеваемых объединений. Тогда я бы использовал производную таблицу вместо коррелированного подзапроса (Никогда не используйте коррелированный подзапрос, поскольку они являются собаками производительности!)

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, потому что вы не дали нам никаких указаний на то, как выбирать, какие записи в таблице ссуд выбрать, когда вы хотите только одну. Тем не менее, я подозреваю, что есть лучший способ (или, по крайней мере, я надеюсь, что у вашего дизайна есть лучший способ) найти книгу, которая уже вышла. Возможно, у вас есть поле, которое указывает, что книга была возвращена, или, возможно, вы хотите, чтобы была возвращена дата первой доступной книги, а не самая последняя дата. Не используйте Макс, не думая о том, как получить только одну запись. В противном случае вы можете написать запрос, который работает, но он неверен в своих результатах. На основании вашего комментария ниже я пересмотрел запрос.

Ключ к пониманию этого заключается в том, что производная таблица должна возвращать запись, которая еще не была возвращена, но которая должна быть доступна в ближайшее время (т.е. она имеет самую раннюю дату исполнения). Если мой запрос не делает этого, то вам нужно будет поэкспериментировать, пока вы не найдете тот, который делает. Заключительный пункт, где может или не может быть необходимым, вы должны проверить это также. Это зависит от того, являются ли номера книг уникальными или повторяются ли они для разных книг.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...