Greatest n-per-group With Multiple Joins

2019-09-03 14:29发布

问题:

Evening,

I am trying to get an output of rows that are limited to n per group in MySQL. I can get it to work without joins, but with it I am just shy. I've pasted a dump of the relevant tables here:

http://pastebin.com/6F0v1jhZ

The query I am using is:

SELECT
   title, catRef, RowNum, pCat, tog
FROM
(
    SELECT
        title, catRef,
        @num := IF(@prevCat=catRef,@num+1,1) AS RowNum,
        @prevCat AS tog,
        @prevCat := catRef AS pCat
    FROM (select @prevCat:=null) AS initvars
    CROSS JOIN 
    (
        SELECT p.title, oi.catRef
        FROM resources p
        INNER JOIN placesRel v ON (p.resId = v.refId)
        INNER JOIN catRel oi ON (p.resId = oi.refId)
        WHERE p.status = 'live' AND v.type = 'res' AND oi.type = 'res'
    ) AS T
) AS U
WHERE RowNum <= 5
ORDER BY catRef

I just can't get the row count to go up. Or any other solution would be greatly appreciated.

I'm looking for a result like this:

title        catRef        RowNum
Title1       1             1
Title2       1             2
Title3       1             3
Title4       2             1
Title5       2             2
Title6       3             1

At the moment, the RowNum column is always 1.

回答1:

This works:

SET @num := 1, @prevCat := 0;
SELECT title, start, end, type, description, linkOut, outType, catRef, row_number
FROM (
SELECT title, start, end, type, description, linkOut, outType, catRef,
@num := if(@prevCat = catRef, @num + 1, 1) as row_number,
@prevCat AS tog,
@prevCat := catRef AS dummy
FROM (
    SELECT title, start, end, resources.type, description, linkOut, outType, catRef
    FROM resources LEFT JOIN placesRel ON placesRel.refId = resId LEFT JOIN catRel ON catRel.refId = resId
    WHERE status = 'live' AND placesRel.type = 'res' AND catRel.type = 'res'
    ORDER BY catRef
) AS w
) AS x WHERE x.row_number <= 4;

You need to put your joined query in a sub-query and order it by the column you want to group by. Use it's parent query to add row numbers. Then, the top-level query glues it all together.

If you don't put your joined query in it's own sub-query, the results won't be ordered as you wish, but instead will come out in the order they are in the database. This means the data is not grouped, so row numbers will no be applied to ordered rows.