Pregunta

Estoy intentando ejecutar esta consulta:

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

Esto me va a obtener un número de artículos (de nt_noticias) y la idea es conseguir al mismo tiempo una Video y un archivo Audio de la mesa mm_files.

Lo que sucede es que cuando tengo un artículo con un sonido y un vídeo, MySQL retornará 4 filas:

  • con el sonido (vídeo es nulo)
  • con el vídeo (sonido es nulo)
  • con todos los nulos
  • con el sonido y el vídeo

¿Cómo puedo "forzar" a devolver sólo una fila por cada artículo con cualquier video existente y audio asociado? ¿Qué estoy haciendo mal aquí?

¿Fue útil?

Solución

piensan ¿Quieres algo como esto:

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

Mi idea era la siguiente:

¿Quieres un archivo de audio y un archivo de vídeo, como máximo. Hay varios archivos disponibles por Noticia, por lo que necesita para asegurarse de que un máximo de un archivo por cada tipo se mete en la unión. Esto también significa que tiene que unirse a la mesa de ntNoticias_mmFiles dos veces -. Una vez al tipo

Esto es lo que se supone que los sub-consultas en las condiciones de combinación que hacer: Seleccionar una fila por cada tipo de archivo. Y pasando de allí te dejó unirse al resto de los datos en, al igual que ya lo hacen.

Otros consejos

La unión devolverá todas las combinaciones, ese es el problema.
Si sólo tiene un audio y / o archivo de vídeo por artículo entonces es posible que desee ver en subselects. En SQL Server esto sería algo como (código no probado):

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

Tenga cuidado de que en grandes conjuntos de datos esto puede realizarse mal como los subselects en este ejemplo se ejecutan de forma individual para cada fila devuelta a la consulta externa. Por ejemplo, si usted vuelve 10.000 artículos a continuación, un total de 20.001 consultas en realidad se ejecuta en el servidor. Hay otras respuestas posibles para superar esto, pero que se involucren más (sospecho que podría hacer algo con una tabla derivada, pero se me escapa por el momento).

Es posible que desee optimizar esa consulta de combinación en una vista. Es una consulta de gran tamaño, y con el que muchos se une, que va a ser bastante ineficiente. Además, una vista ayuda a depurar las uniones y, básicamente, simplifica al permitir que usted escriba su une (en la vista) y la cláusula WHERE (en su selecto de la vista) por separado, que puede ayudar con la depuración de las consultas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top