Чисто навскидку:
Tags
-tag_id:int
-tag:char/varchar
Cagegories
-category_id:int
-category:char/varchar
Notes:
-note_id:int
-note:text
-created_at:datatime
-updated_at:datetime
-category:FK->Cagegories
Notes_tag:
note:FK->Notes
tag:FK->Tags
Схема запроса примерно следующая (очень условная, чисто показать принцип):
select *.n, category.c, from Notes n, Cagegories c
join JSON_ARRAYAGG (запрос к Notes_tag)
order by created_at desc
limit [from] [to]
upd:
При запросе динамически подставлять значения в [from] [to]
Пример join`а JSON_ARRAYAGG (нашел в инете)
https://www.db-fiddle.com/f/mUJLe4gPw9CZyLcfS3wrMY/0