Подзапрос возвращает более одной строки SQL

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

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

Мои таблицы, которые я использую для этого,

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

спасибо рк


person Community    schedule 25.08.2009    source источник
comment
Я пометил это как sql и tsql, чтобы указать, что это связано с запросом к базе данных. Если это не SQL Server, просто вытащите бит tsql (но ваша проблема действительна в tsql, поэтому я думаю, что стоит оставить там)   -  person Rob Farley    schedule 25.08.2009


Ответы (2)


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

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 может оказаться необходимым, а может и не потребоваться, вы также должны это проверить. Это зависит от того, уникальны ли номера книг или они повторяются для разных книг.

person HLGEM    schedule 26.08.2009
comment
Привет, HLGEM, спасибо за отзыв. Да, вы правы в том, что хотите указать дату выхода первой доступной книги. Не могли бы вы объяснить лучший способ, о котором вы упомянули выше. В моей таблице ссуд есть дополнительный столбец, который я пропустил (dateout) ссуд: student_id, book_no, duedate, datereturned, dateout, ссудный_id fk: book_no с book_no в book_copy fk: student_id с student_id в таблице учеников Извините, если я неправильно понял то, что вы сказали. Будет ли Макс по-прежнему лучшим вариантом? - person ; 28.08.2009
comment
rk, я отредактировал свой ответ, чтобы отразить вашу новую информацию. Макс был бы совершенно неподходящим для вашей ситуации. - person HLGEM; 28.08.2009
comment
Большое спасибо за ответ, Hlgem, запрос, похоже, не работает. Я изучаю его. В моей таблице книг нет копии книги без столбца, она просто идентифицирует каждую книгу по isbn. Каждая книга имеет уникальный isbn, но в таблице экземпляров книги isbn повторяется, если имеется более одной копии книги (поэтому isbn в книжной копии повторяется). Куда я иду надеть? Спасибо - person ; 28.08.2009
comment
Посмотри, работает ли это. В противном случае вам нужно будет присоединить кредит к book_copy_to book, чтобы получить то, что вам нужно, в производной таблице. - person HLGEM; 28.08.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.

Роб

person Rob Farley    schedule 25.08.2009
comment
Большое спасибо, Роб, твоя помощь очень ценится. Это сработало - person ; 25.08.2009
comment
@Rk: не могли бы вы оказать сообществу услугу и отметить этот вопрос как «отвеченный», установив флажок под стрелкой «против»? - person dance2die; 25.08.2009