2009-12-19 2 views
0

У меня есть база данных MySQL с двумя таблицами (упрощенных по этому вопросу):
кино столбцов таблицы: id, title, duration, description, created_at, updated_at
аренды столбцов таблицы: id , movie_id, status, created_at, updated_atВозврат только уникальный идентификатор таблицы от MySQL присоединиться к

статус аренды либо «Выдан» или «ВЕРНУЛСЯ», так что фильм доступен, если он либо не имеет связанную аренды, или все связанные с ним реном tals имеют статус «ВОЗВРАЩЕН». Как запросить доступные фильмы? Сейчас у меня есть это:

SELECT rentals.id,rentals.status,movies.* 
FROM `movies` 
LEFT OUTER JOIN rentals ON movies.id = rentals.movie_id 
     AND movies.kiosk_id = rentals.kiosk_id 
WHERE (`movies`.kiosk_id = 1 
     AND (rentals.id is null or rentals.status != 'CHECKED OUT')); 

Проблема заключается в том, этот запрос возвращает несколько записей для фильма, если он был проверен несколько раз, так что мой ORM дает мне дублировать объекты кино. Есть ли способ указать, что мне нужен только уникальный movie.id? Должен ли я иметь некоторую другую схему базы данных? Или я должен разобраться в нем программно (похоже, это было бы слишком медленно)?

ответ

2

Я не уверен, что вы хотите с идентификатором арендной платы, поэтому я взял его.

SELECT 
    rentals.status, movies.* 
FROM movies 
LEFT OUTER JOIN (
    SELECT 
    movie_id, 
    kiosk_id, 
    -- Because 'CHECKED OUT' comes alphabetically before 'RETURNED', 
    -- this will have 'CHECKED OUT' if there's at least one rental checked out 
    MIN(status) AS status 
    FROM rentals 
    GROUP BY movie_id, kiosk_id) rentals 
ON movies.id = rentals.movie_id 
AND movies.kiosk_id = rentals.kiosk_id 
WHERE movies.kiosk_id = 1 
AND (rentals.id is null or rentals.status != 'CHECKED OUT'); 
+0

, единственная проблема с вашим ответом заключалась в том, что мне нужно было добавить «id» после второго выбора, но после этого он работал хорошо , благодаря! – aaronstacy

0

Я думаю, вы хотите, чтобы в вашем запросе была найдена отдельная rent.id. попробуйте следующее:

SELECT DISTINCT rentals.id,rentals.status,movies.* 
FROM `movies` 
LEFT OUTER JOIN rentals ON movies.id = rentals.movie_id 
     AND movies.kiosk_id = rentals.kiosk_id 
WHERE (`movies`.kiosk_id = 1 
     AND (rentals.id is null or rentals.status != 'CHECKED OUT')); 
+0

нет, когда я добавить DISTINCT к запросу он будет таким же, как без него. есть ли способ указать, какое поле должно быть разным? – aaronstacy

+0

это не сработает, потому что вполне вероятно, что каждая аренда имеет свой собственный идентификатор. Таким образом, в результирующем событии без DISTINCT не будет * дубликатов *, но будет дублироваться movie.id – Dmitry

0

Почему ЛЕВОЙ ВНЕШНИЙ ВХОД? Достаточно просто LEFT JOIN.

Вы также должны переместить rentals.status в положение ON() немного (я думаю):

SELECT DISTINCT movies.id, movies.*, rentals.id, rentals.status 
FROM `movies` 
LEFT JOIN rentals ON (movies.id = rentals.movie_id AND movies.kiosk_id = rentals.kiosk_id AND rentals.status != 'CHECKED OUT') 
WHERE `movies`.kiosk_id = 1 AND rentals.id is null 

// Редактировать Вам также необходимо отчетливое

+0

«LEFT JOIN» и «LEFT OUTER JOIN» - это то же самое. –

0

Ваша проблема, что вы хотите результат не имеет смысла. Вы хотите, чтобы доступные фильмы - это нормально, но что означал бы идентификатор аренды в одной строке с некоторым идентификатором фильма? Вы должны выбросить прокат в списке SELECT, и после этого наклеивания DISTINCT только movies.id будет делать трюк

0

Если вам нужны все доступные фильмы для проката вы можете попробовать это: SELECT movies.* FROM movies LEFT JOIN ( SELECT DISTINCT movie_id FROM rentals WHERE status!='CHECKED OUT' AND kiosk_id=1) r ON movies.movie_id=r.movie_id

Смежные вопросы