Search code examples
mysqlgreatest-n-per-group

LIMIT RESULTS RETURNED BASED ON DB VALUE


I have two tables, Categories, and Stories.

The Stories table contains content organized by category.

categories_id, category_name, category_story_count
1, news, 2
2, funnies, 3

stories_id, categories_id, story_name, story_content, story_active
1, 1, "Tax Hike", "blah blah", 1
2, 1, "Tax Cuts", "blah blah", 1
2, 1, "Election", "blah blah", 1 
4, 2, "Peanuts", "blah blah", 1
5, 2, "Garfield", "blah blah", 1
6, 2, "Archie", "blah blah", 1 

I want a query which will return the correct number of stories for each category based on the category_story_count, and if the story is active (story_active = 1)

So the result should look like:

"news", "Tax Hike"
"news", "Tax Cuts"
"funnies", "Peanuts"
"funnies", "Garfield"
"funnies", "Archie"

Two "news" stories because news category 1, has a category_story_count = 2, and three "funnies", because funnies 2, has a category_story_count = 3

I've experimented with inner joins, nested, and limits, but just can't get it to return what I'm aiming for.

Any help would be appreciated.

EDIT: MySQL VERSION() 8.0.23


Solution

  • Here's a solution using window functions:

    with cte as ( 
      select *, row_number() over (partition by c.categories_id order by s.stories_id) as rownum 
      from Categories as c join Stories as s using (categories_id) 
    ) select * from cte where rownum <= category_story_count;
    
    +---------------+---------------+----------------------+------------+------------+---------------+--------------+--------+
    | categories_id | category_name | category_story_count | stories_id | story_name | story_content | story_active | rownum |
    +---------------+---------------+----------------------+------------+------------+---------------+--------------+--------+
    |             1 | new           |                    2 |          1 | Tax Hike   | blah blah     |            1 |      1 |
    |             1 | new           |                    2 |          2 | Tax Cuts   | blah blah     |            1 |      2 |
    |             2 | funnies       |                    3 |          4 | Peanuts    | blah blah     |            1 |      1 |
    |             2 | funnies       |                    3 |          5 | Garfield   | blah blah     |            1 |      2 |
    |             2 | funnies       |                    3 |          6 | Archie     | blah blah     |            1 |      3 |
    +---------------+---------------+----------------------+------------+------------+---------------+--------------+--------+
    

    Tested on MySQL 8.0.23.