I have 2 tables with 50k+ & 10k+ rows
Table chapter
id (auto_inc) | chapter_id | story_id | date (timestamp)
1 | 1 | 1 | 1715830560
...
10 | 10 | 1 | 1715830570 <- latest chapter of story #1
100 | 1 | 2 | 1715830560
...
111 | 11 | 2 | 1715830570 <- latest chapter of story #2
200 | 1 | 3 | 1715830560
...
211 | 21 | 3 | 1715830570 <- latest chapter of story #3
Table story
id (auto_inc) | slug | title | date (timestamp)
1 | slug-1 | title 1 | 1715830560
...
100 | slug-100 | tit 100 | 1715830580 <- consider this is latest story
I used this command below to get the latest unique chapter of each story
SELECT C.id, MAX(C.chapter_id), C.story_id, C.title AS title_chapter, C.summary
FROM `chapter` C
GROUP by C.story_id
ORDER by C.id DESC
LiMIT 10;
It shows successfully the 10 unique stories with their chapters, but it always picks chapters by the latest story, mean it always pick the latest stories first then pick the latest chapters for each story; result like below:
id | chapter_id | story_id (↓) | date (timestamp)
205 | 5 | 100 | 1715830560 <- 205 is latest chapter of story #100
108 | 8 | 99 | 1715830560 <- ..
8 | 8 | 98 | 1715830560 <- ..
But I want latest chapter sorted by id, mean the latest chapter of stories, not latest stories with chapter, result like below:
id (↓) | chapter_id (latest of each story) | story_id (unique) | date (timestamp)
508 | 15 | 75 | 10
507 | 35 | 95 | 9
506 | 5 | 15 | 8
505 | 15 | 100 | 8
504 | 35 | 99 | 8
And please suggest me the solution (best performance with minium processing time) to get title & slug from story
table for these latest chapters.
Many thanks for advising.
Your current query is invalid, because it aggregates by the story_id
, but then selects non aggregate columns. Your code would not even run on MySQL with the ONLY_FULL_GROUP_BY
flag enabled. A canonical approach to your problem would use the ROW_NUMBER()
window function:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY story_id ORDER BY chapter_id DESC) rn
FROM chapter
)
SELECT id, chapter_id, story_id, title AS title_chapter, summary
FROM cte
WHERE rn = 1
ORDER BY date DESC
LIMIT 10;
For MySQL 5.7 or earlier:
SELECT c1.id, c1.chapter_id, c1.story_id, c1.title AS title_chapter, c1.summary
FROM chapter c1
INNER JOIN (
SELECT story_id, MAX(chapter_id) AS max_chapter_id
FROM chapter
GROUP BY story_id
) c2
ON c2.story_id = c1.story_id AND
c2.max_chapter_id = c1.chapter_id
ORDER BY c1.date DESC
LIMIT 10;