我有这样的查询:
SELECT
p.title,
a.title
FROM
pages p
LEFT JOIN
articles_pages ap on ap.p_id = p.id
LEFT JOIN
articles a ON a.id = p.a_id
WHERE
[...]
LIMIT 10
如何限制每页只有3篇文章?
答案 0 :(得分:0)
有几种方法可以做到这一点。您可以使用子查询,但我不建议使用较慢且不可扩展的子查询。所以..我喜欢我向你展示的那个:
我会创建一个变量并在其上保存行号(@num)。
我们还需要另一个变量来保存“页面”ID,以便在出现其他页面时重新启动行计数。
最后,我们用@num过滤你想要的行数。请记住,matchNO是一个计算字段,因此您无法过滤where where statment,而是使用。
set @num := 0, @page := 0;
SELECT p.title, a.title,IF(@page = p.id,@num:=@num+1,@num:=1) as matchNO,@page:=p.id
FROM pages p
LEFT JOIN articles_pages ap on ap.p_id = p.id
LEFT JOIN articles a ON a.id = p.a_id
WHERE [...]
having matchNO <= 3
LIMIT 10
行号是必要的,以确定你是在哪一行。 页面变量告诉您最后一行中的页面,以便您可以进行比较,然后在必要时再次将@num设置为1.
我希望它有所帮助
答案 1 :(得分:0)
您可以使用用户变量生成行号,然后根据它进行过滤。
select p.title, a.title
from (
select
t.*,
@rn := if(
@id = id, @rn + 1,
if(
@id := id, 1, 1
)
) rn
from (
select *
from pages
order by id, a_id
) t cross join (select @rn := 0, @id:= -1) t2
) p left join articles a on a.id = p.a_id
where p.rn <= 3
order by p.id, p.a_id;
答案 2 :(得分:0)
另一种可能的方法。这是否会比其他更好或更差取决于页面和文章的相对数量。
您可以使用子查询每页获得3篇文章,然后将其加入到您的表中。您可以作弊并使用GROUP_CONCAT获取每个文章的所有文章的ID,然后使用SUBSTRING_INDEX获取前3个(如果需要,可以向GROUP_CONCAT添加一个order子句),然后使用FIND_IN SET加入它。 / p>
SELECT
p.title,
a.title
FROM pages p
LEFT OUTER JOIN
(
SELECT ap.p_id
SUBSTRING_INDEX(GROUP_CONCAT(ap.a_id), ',', 3) AS three_articles_per_page
FROM articles_pages ap
GROUP BY ap.p_id
) sub0 ON p.id = sub0.p_id
LEFT JOIN articles_pages ap on ap.p_id = p.id AND FIND_IN_SET(ap.aid, sub0.three_articles_per_page)
LEFT JOIN articles a ON a.id = p.a_id
WHERE
[...]