There are two tables.
ArArticles
List of articles posted by users
FFavorites
List of articles that users have registered as favorites
The article and its information are registered in には.
② will have the id (main key of 1) and user ID of the article registered as your favorite in the column.
When extracting a list of favorites, you are unsure which of the following two methods to choose.
A proposal
②Obtained the article ID registered by the user from the .
After that, a list of articles is acquired from から on condition of the ID.
$article_ids=Favorite::where('user_id', $user_id)->pluck('article_id');
$articles=Article::whereIn('id', $article_ids)->get();
B proposal
A list of articles is acquired by combining と and を by an article ID on the condition of a user ID.
$articles=Favorite::leftJoin('articles', 'favorites.article_id', '=', 'articles.id')
->where('favorites.user_id', $user_id) ->get();
I'm concerned about the following:
(1) In such a case, which method is orthodox, A or B?
(2) Which one has better performance?
A has issued two SQL internally.
B performs the process of high cost combination.
(3) Which method is better overall?
Thank you for your cooperation.
sql laravel
Fine-tune without permission.Also, start with :query()
to make it compatible with IDE and easy to match indentation.
//A: Two consecutive SQL issues at WHERE IN (1, 2, 3, ...)
$article_ids=Favorite::query()
->where('user_id', $user_id)
->pluck('article_id');
$articles=Article::query()
->find($article_ids);
// B: Use JOIN
$articles=Article::query()
->leftJoin('favorites', 'favorites.article_id', '=', 'articles.id')
->where('favorites.user_id', $user_id)
->select('articles.*')
->get();
// C: Correlation subqueries using WHERE EXISTS (SELECT...)
$articles=Article::query()
->whereHas('favorites', function(Builder$query)use($user_id){
$query->where('user_id'=>$user_id);
})
->get();
// D: Non-relevant subqueries using WHERE IN (SELECT...)
// // https://github.com/mpyw/eloquent-has-by-non-dependent-subquery
$articles=Article::query()
->hasByNonDependentSubquery('favorites', function(Builder$query)use($user_id){
$query->where('user_id'=>$user_id);
})
->get();
It's the simplest code, but when you try to add pageation, you think a little more.Also, pageation is difficult with information only found in the articles
table.Therefore, only a limited number of cases are available.
This is the best performance code, but it uses a lot of landmines.Please note the following:It's a good idea for non-skilled people to use it.
HasMany
There is a risk of duplicate records of the same ID appearing for the relationship.There is a limitation that says, "Only one user can like the same article," and there is no problem if you narrow it down to a single user_id
.Also, HasOne
BelongsTo
is perfectly fine.->select('articles.*')
Don't forget to give it.Without it, the favorites
fields will be mixed into creating a disastrous bug.Article::query()
.Favorite::query()
results in an instance of Favorite
.Probably the most orthodox method.It can be used in many situations and is a safe method, but query optimizer is not smart MySQL, and the performance is blatantly degraded.There is no problem with PostgreSQL.
This code uses my own library to solve problems with C in MySQL.It's negative from an orthodox point of view, but it's both easy to use and high performance.
© 2024 OneMinuteCode. All rights reserved.