Laravel 5.6.9 - database count gives different outputs - sql

Does anyone know why these two ways to count numbers of users in my table give different answers when i run them in tinker?
App\Models\User::count()
=> 92269
$count = \DB::table('users')->count()
=> 92829
Running a SQL query in Sequel Pro gives 92829.

If you have the SoftDelete trait on your User model then when you query via the Model it excludes "deleted" entries. You can include them by adding the withTrashed() constraint.
App\Models\User::withTrashed()->count();
https://laravel.com/docs/7.x/eloquent#soft-deleting

Related

When an user views all articles, see their own articles first

we have two models
article
user
user have many articles
i need When an user views all articles, see their own articles first.
my idea
make two query
first query return articles related to query
Article.where(user_id: user_id)
second query
Article.where.not(user_id: user_id)
and merge result
second Idea
get all articles and select method in ruby
but i need best way make this
i use Ruby On Rails 6.1 and Ruby 3
You could run one query but sort the articles with SQL depending on if they have a matching user_id:
Article.order(Arel.sql("CASE user_id WHEN #{user_id} THEN 0 ELSE 1 END"))
Note: order does not support multiple arguments and input sanitization out of the box. Use this only, when you are sure that the user_id contains only a valid user id, for example, be using current_user.id instead of user_id
In Rails 7 there will be a new method called in_order_of which would allow writing the same functionality like this:
Article.in_order_of(:user_id, user_id)
More programmatic approach
articles = Article.arel_table
case_statement = Arel::Nodes::Case.new(articles[:user_id])
.when(user_id)
.then(0)
.else(1)
Article.order(case_statement)

CakePHP 3 ORM - Sorting based on two columns in two different related tables

Currently I'm trying to implement timeline functionality which requires to sort the created column in two related tables and update the parent table (in my case pictures) accordingly.
More specific, I have a pictures table which has many comments. I want to sort the pictures based on the most recent timestamp in the created column of both the comments and pictures table.
I have the following query which retrieves the necessary data but it isn't ordered properly:
public function getPicturesAndCommentsOfUser($userId){
return $this->find()
->contain([
'Comments' => function ($q){
return $q
->contain(['Users' => function ($q) {
return $q->select($this->select);
}])
->order(['Comments.created' => 'ASC']);
},
'Users' => function ($q) {
return $q->select($this->select);
},
'Albums'
])
->matching('Albums.Users', function ($q) use ($userId) {
return $q
->where(['Users.id' => $userId]);
});
}
My question is how to combine both the ordering of Pictures.created and Comments.created. I already tried to call the order function in both ->contain(['Comments']) and in the most outer part of the chain after the last matching call. I can't seem to figure out how to relate the two tables to each other so that I can sort on both of them.
Moreover, I read in other sources (like this one) that I could use an union statement but all the information I can find about that option is that it will work on unrelated tables, not related.
Anyone can give me some directions on how to solve this?
First of all your purpose should be clear. Which ordering has priority for you? Pictures.created or Comments.created? You can not sort the results based on both. When you do something like this:
$this->Comments->find()->order(['Pictures.created' => 'ASC'])->
order(['Comments.created' => 'ASC']);
The ordering is only guaranteed for Comments.created. If two comments had equal times then they are ordered by Pictures.created.
There's another thing to be considered. Build the query on the object that is more populated. If each Picture HasMany Comments try to build your query on Comments. I don't have any idea how the results get sorted when you are building the query on Pictures. Because the retrieved records are sorted not by Pictures.id but when the result is translated to object models, Comments are nested in Pictures and previous orderings get disposed.
And at last don't make things complicated. Using php logic in queries doesn't improve the performance, otherwise it decreases your code readability. So if you are about to perform php logic first retrieve all data then process it using several simple foreaches.

Join with subquery in Django ORM

I want to run a filter using Django's ORM such that I get a distinct set of users with each user's most recent session. I have the tables set up so that a user has many sessions; there is a User and Session model with the Session model having a user = models.ForeignKey(User).
What I've tried so far is Users.objects.distinct('username').order_by('session__last_accessed'), but I know that this won't work because Django puts the session.last_accessed column into the selection, and so it's returning me, for example, 5 duplicate usernames with 5 distinct sessions rather than the single recent session and user.
Is it possible to query this via Django's ORM?
Edit: Okay, after some testing with SQL I've found that the SQL I want to use is:
select user.username, sub_query.last_accessed from (
select user_id, max(last_accessed) as last_accessed
from session
group by user_id
) sub_query
join user on
user.id = sub_query.user_id
order by sub_query.last_accessed desc
limit 5
And I can do sub_query via Session.objects.values('user').annotate(last_accessed=Max('last_accessed')). How can I use this sub_query to get the data I want with the ORM?
Edit 2: Specifically, I want to do this by performing one query only, like the SQL above does. Of course, I can query twice and do some processing in Python, but I'd prefer to hit the database once while using the ORM.
If you are using mysql backend, the following solution can be useful:
users_in_session = Session.objects.values_list('user_id', flat=True)
sessions_by_the_user_list = Session.objects \
.filter(user__in=set(users_in_session)) \
.order_by('last_accessed').distinct()
If you use the sub_query, then order_by('last_accessed') function should be good enough to get data in ordered list. Although as far as I have tested these results seemed unstable.
Update:
You can try:
Session.objects.values('user') \
.annotate(last_accessed=Max('last_accessed')) \
.orde‌​r_by('last_accessed').distinct()
Calling distinct('username') shouldn't return duplicate usernames ever. Are you sure you are using Django version that supports .dictinct(fields), that is Django version later than 1.4? Prior to Django 1.4 .distinct(fields) was accepted by the oRM, but it didn't actually do the correct DISTINCT ON query.
Another hint that things aren't working as expected is that .distinct(username).order_by(session__last_accessed) isn't a valid query - the order_by should have username as first argument because order_by must be prefixed with the field names in .distinct() call. See https://docs.djangoproject.com/en/1.4/ref/models/querysets/#django.db.models.query.QuerySet.distinct for details.

Rails .joins doesn't load the association

Helo,
My query:
#county = County.joins(:state)
.where("counties.slug = ? AND states.slug = ?", params[:county_slug])
.select('states.*, counties.*')
.first!
From the log, the SQL looks like this:
SELECT states.*, counties.* FROM "counties" INNER JOIN "states" ON "states"."id" = "counties"."state_id" LIMIT 1
My problem is that is doesn't eager load the data from the associated table (states), because when I do, for example, #county.state.name, it runs another query, although, as you can see from the log, it had already queried the database for the data in that table as well. But it doesn't pre populate #county.state
Any idea how i can get all the data from the database in just ONE query?
Thx
I think you need to use include instead of joins to get the eager loading. There's a good railscasts episode about the differences: http://railscasts.com/episodes/181-include-vs-joins , in particular:
The question we need to ask is “are we using any of the related model’s attributes?” In our case the answer is “yes” as we’re showing the user’s name against each comment. This means that we want to get the users at the same time as we retrieve the comments and so we should be using include here.

Query Returning the same record multiple times

I have a query that should return 72 unique records based on the userid field. The problem is that what I am getting is 72 copies of the first record.
Here is the query:
return Session
.CreateCriteria()
.Add(Restrictions.Eq("UserId", id))
.List();
and here is what NUnit is running for the query:
SELECT this_.USER_ID as USER1_12_0_, this_.RIGHTS_ID as RIGHTS2_12_0_, this_.FUNCTIONAL_AREA as FUNCTIONAL3_12_0_, this_.PERM_RIGHTS_ID as PERM4_12_0_ FROM PROFILE this_ WHERE this_.USER_ID = :p0;:p0 = 7943
When this query is run directly against Oracle - the results are correct.
Try using a mapping file generator and compare your mapping files as the problem most likely lies in your mapping files. There a plenty listed at http://nhforge.org/wikis/general/open-source-project-ecosystem.aspx. NhGen (http://sourceforge.net/projects/nhgen/) includes some very basic unit tests which might also assist you.