我正在尝试运行此查询:
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
),我们的想法是同时从Video
获取Audio
和mm_files
文件表
当我有一篇有声音和视频的文章时,MySQL会返回4行:
我如何“强制”它每篇文章只返回一行,并且与现有的视频和音频相关联?我在这里做错了什么?
答案 0 :(得分: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个查询。 还有其他可能的答案可以解决这个问题,但是他们会更多地参与其中(我怀疑你可以用衍生的表做些什么,但目前我不能这样做。)
答案 1 :(得分: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
表 - 每种类型一次。
这是连接条件中的子查询应该执行的操作:为每种文件类型选择一行。从那里继续你LEFT JOIN其余的数据,就像你已经做的那样。
答案 2 :(得分:0)
您可能希望将该连接查询优化到视图中。这是一个很大的查询,并且有很多连接,它的效率会非常低。此外,一个视图可以帮助您调试连接,并且基本上可以通过允许您分别编写连接(在视图中)和WHERE子句(在视图中选择)来简化,这可以帮助调试查询。