MYSQL如何限制连接的结果

时间:2017-02-28 14:27:43

标签: mysql sql

我有这样的查询:

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篇文章?

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;

Demo

答案 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 
    [...]