چطور یه کوئری ساده SQL کار نمیکنه!

تو یه بخشی از یه پروژه، سه تا جدول داشتم برای اخبار، تگ اخبار و ارتباط بینشون. میخواستم مثلا اخباری که تگ‌های اقتصادی داری رو در بیارم. اول یه همچین چیزی نوشتم.

select * from news 
inner join news_tag on news_tag.news_id = news.id
inner join tag on news_tag.tag_id = tag.id
where tag.name like '%something%'
order by news.published_at desc
limit 50

به نظر مشکلی نبود. ولی دیدم تو نتایج خبر تکراری هست. با یکم تحقیق و پرسش فهمیدم که اصلا مشکل این کوئری اینه که امکان داره نتیجه تکراری بده.

چطور؟ فرض کنید دو تا تگ داریم، به اسم‌های اقتصادی و اقتصاد خاورمیانه. اگه یه پستی این دو تگ رو داشته باشه، دو بار در نتایج ظاهر میشه، یه بار به خاطر تگ اقتصادی و یه بار به خاطر تگ اقتصاد خاورمیانه. بیشتر هم میتونه بشه، سه تا تکراری هم دیدم تو نتایج.

حتی اگه نتایج تکراری رو تو کد حذف کنیم، مشکل اینجاست که ۵۰ تا میخوایم. دیتابیس هم ۵۰ تا میده و تکراری توشه. راهی نیست که بهش بگی ۵۰ تا غیرتکراری بده. وقتی تو کد تکراری‌ها رو حذف میکنیم، نتایج کمتر از ۵۰ تا میشن که خب مشکل داره. ما ۵۰ تا میخوایم.

نتیجه سرچ و پرسش این کوئری شد.

select id from news as n
where exists (select id from tags as t join news_tag nt on t.id = nt.tag_id where nt.news_id = n.id and t.name like '%something%')
order by published_at desc
limit 50

این باعث میشه که بتونیم دقیقا ۵۰ تا خبر غیر تکراری رو بگیریم. من در مورد sub-query ها میدونستم، ولی در مورد exists نمیدونستم.

من از postgresql استفاده کردم، ولی احتمالا تو بقیه rdbms ها هم exists هست و میشه استفاده کرد.