2009-05-23 4 views
3

Я пытаюсь запустить этот запрос:MySQL с 2 СЛЕВА JOIN и на том же столе

SELECT 
    Destaque.destaque, Noticia.id, Noticia.antetitulo, 
    Noticia.titulo, Noticia.lead, Noticia.legenda, 
    Noticia.publicacao, Seccao.descricao, Album.pasta, 
    Foto.ficheiro, Foto.descricao, Cronista.nome, 
    Cronista.profissao, Cronista.ficheiro, 
    AudioFile.*, AudioCollection.*, VideoFile.*, VideoCollection.* 
FROM 
    nt_highlights AS Destaque 
    LEFT JOIN nt_noticias AS Noticia   ON Destaque.noticia_id = Noticia.id 
    LEFT JOIN mm_fotos  AS Foto   ON Noticia.foto_id = Foto.id 
    LEFT JOIN nt_temas  AS Seccao   ON Noticia.tema_id = Seccao.id 
    LEFT JOIN mm_albuns AS Album   ON Foto.album_id = Album.id 
    LEFT JOIN nt_cronistas AS Cronista  ON Cronista.id = Noticia.cronista_id 
    LEFT JOIN ntNoticias_mmFiles AS Rel  ON Rel.noticia_id = Noticia.id 
    LEFT JOIN mm_files  AS AudioFile  ON AudioFile.id = Rel.file_id 
    LEFT JOIN mm_coleccoes AS AudioCollection ON AudioFile.coleccao_id = AudioCollection.id   
    LEFT JOIN mm_files  AS VideoFile  ON VideoFile.id = Rel.file_id 
    LEFT JOIN mm_coleccoes AS VideoCollection ON VideoFile.coleccao_id = VideoCollection.id 
WHERE 
    Destaque.area_id = 1 
    AND Noticia.paraPublicacao = 1 
    AND Noticia.publicacao <= NOW() 
    AND (AudioFile.mimeType != '' OR AudioFile.id IS NULL) 
    AND (VideoFile.mimeType = '' OR VideoFile.id IS NULL) 
ORDER BY 
    Destaque.destaque 

Это поможет мне ряд статей (из nt_noticias) и идея заключается в том, чтобы получить в то же время a Video и файл Audio из таблицы mm_files.

Что происходит, что когда у меня есть статья со звуком и видео, MySQL вернет 4 строки:

  • со звуком (видео нуля)
  • с видео (звук пустой)
  • со всеми нулям
  • с звуком и видео

Как я могу «заставить» его вернуть только одну строку за статью с y существующее видео и аудио? Что я здесь делаю неправильно?

ответ

1

Я думаю вы хотите что-то вроде этого:

SELECT 
    Destaque.destaque, Noticia.id, Noticia.antetitulo, 
    Noticia.titulo, Noticia.lead, Noticia.legenda, 
    Noticia.publicacao, Seccao.descricao, Album.pasta, 
    Foto.ficheiro, Foto.descricao, Cronista.nome, 
    Cronista.profissao, Cronista.ficheiro, 
    AudioFile.*, AudioCollection.*, VideoFile.*, VideoCollection.* 
FROM 
    nt_highlights AS Destaque 
    LEFT JOIN nt_noticias AS Noticia   ON Destaque.noticia_id = Noticia.id 
    LEFT JOIN mm_fotos  AS Foto   ON Noticia.foto_id = Foto.id 
    LEFT JOIN nt_temas  AS Seccao   ON Noticia.tema_id = Seccao.id 
    LEFT JOIN mm_albuns AS Album   ON Foto.album_id = Album.id 
    LEFT JOIN nt_cronistas AS Cronista  ON Cronista.id = Noticia.cronista_id 
    LEFT JOIN ntNoticias_mmFiles AS AudioRel ON Rel.noticia_id = Noticia.id 
               AND AudioRel.file_id IN (
    SELECT file_id 
    FROM ntNoticias_mmFiles 
    WHERE noticia_id = Noticia.id AND IsAudioFile = 1 /* whatever the check is */ 
    LIMIT 1 
) 
    LEFT JOIN mm_files  AS AudioFile  ON AudioFile.id = Rel.file_id 
    LEFT JOIN mm_coleccoes AS AudioCollection ON AudioFile.coleccao_id = AudioCollection.id   
    LEFT JOIN ntNoticias_mmFiles AS VideoRel ON VideoRel.noticia_id = Noticia.id 
               AND VideoRel.file_id IN (
    SELECT file_id 
    FROM ntNoticias_mmFiles 
    WHERE noticia_id = Noticia.id AND IsVideoFile = 1 /* whatever the check is */ 
    LIMIT 1 
) 
    LEFT JOIN mm_files  AS VideoFile  ON VideoFile.id = Rel.file_id 
               AND VideoFile.IsVideoFile = 1 
    LEFT JOIN mm_coleccoes AS VideoCollection ON VideoFile.coleccao_id = VideoCollection.id 
WHERE 
    Destaque.area_id = 1 
    AND Noticia.paraPublicacao = 1 
    AND Noticia.publicacao <= NOW() 
ORDER BY 
    Destaque.destaque 

Моя мысль была такова:

Вы хотите один звуковой файл и один файл, в лучшем случае. Доступно несколько файлов на Noticia, поэтому вам нужно убедиться, что в соединение попадает максимум один файл на тип. Это также означает, что вам нужно дважды входить в таблицу ntNoticias_mmFiles — один раз за тип.

Это то, что должны делать подзапросы в условиях соединения: выберите одну строку для типа файла. Отправляясь оттуда, вы ЛЮБИТЕ ПРИСОЕДИНЕНИЕ остальных данных, как и вы.

+0

Предложение LIMIT не работает внутри запроса, потому что я нахожусь в MySQL 5.0, но я заменил его GROUP BY noticia_id и отлично работает. Огромное спасибо! – changelog

+0

Я всегда забываю, что MySQL не обрабатывает LIMIT в подзапросах. :-) Но я рад, что смогу помочь. – Tomalak

1

JOIN вернет все комбинации, вот в чем проблема.
Если у вас есть только один аудио- и/или видеофайлы в каждой статье, вы можете посмотреть подзапросы. В SQL Server это будет выглядеть что-то вроде (непроверенный код):

SELECT title, 
     (select TOP 1 audio from audio where audio.aid = articles.id) as Audio, 
     (select TOP 1 video from video where video.aid = articles.id) as Video 
FROM articles 

Будьте осторожны, что на больших наборах данных, это может плохо работают как подзапросы в этом примере выполняется индивидуально для каждой строки, возвращенной к внешним запросом. Например, если вы вернете 10 000 статей, тогда на сервере будет выполнено всего 20,001 запросов. Есть и другие возможные ответы для преодоления этого, но они становятся все более активными (я подозреваю, что вы могли бы что-то сделать с производной таблицей, но сейчас это ускользает).

0

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

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