40

I am trying to do a where clause on withCount method of laravel's eloquent query builder using this piece of code.

$posts = Post::withCount('upvotes')->where('upvotes_count', '>', 5)->get(); 

and this code is giving me this error.

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'upvotes_count' in 'where clause' (SQL: select , (select count() from upvotes where upvotes.upvoteable_id = posts.id and upvotes.upvoteable_type = App\Post) as upvotes_count from posts where upvotes_count > 5)

So from what I can guess is that upvotes_count isn't selected and hence the column is not being found, BUT if I execute this piece of code.

$posts = Post::withCount('upvotes')->get(); 

Then I am getting this output.

{ "id": 1, "user_id": 15, "title": "Voluptatum voluptas sint delectus unde amet quis.", "created_at": "2016-10-07 13:47:48", "updated_at": "2016-10-07 13:47:48", "upvotes_count": 7 }, { "id": 2, "user_id": 2, "title": "Molestiae in labore qui atque.", "created_at": "2016-10-07 13:47:48", "updated_at": "2016-10-07 13:47:48", "upvotes_count": 2 }, 

Which basically means that upvotes_count is being selected, hence i am really confused about how to solve this problem.

(More options that I tried so far are given below with the respective error associated to it.)

$posts = Post::where('id', $id)->withCount(['upvotes' => function($query) { $query->where('upvotes_count', '>', 5); }])->get(); 

error.

SQLSTATE[42S22]: Column not found: 1247 Reference 'upvotes_count' not supported (forward reference in item list) (SQL: select , (select count() from upvotes where upvotes.upvoteable_id = posts.id and upvotes.upvoteable_type = App\Post and upvotes_count > 5) as upvotes_count from posts where id = 1)

code.

$posts = Post::where('id', $id)->with(['upvotes' => function($query) { $query->select('upvoteable_id AS upvotes_count'); }])->where('upvotes_count', '>', 5)->get(); 

AND

$posts = \App\Post::where('id', $id)->with(['upvotes' => function($query) { $query->selectRaw('upvoteable_id AS upvotes_count'); }])->where('upvotes_count', '>', 5)->get(); 

error.

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'upvotes_count' in 'where clause' (SQL: select * from posts where id = 1 and upvotes_count > 5)


I just want to use where clause on a count() method which is in a relationship with a parent model.

6 Answers 6

48

You can achieve requested result by using:

$posts = Post::withCount('upvotes') ->having('upvotes_count', '>', 5) ->get(); 
Sign up to request clarification or add additional context in comments.

5 Comments

I am still getting the error: column upvotes_count does not exist. I am not sure how this works since from my research it looks like the having clauses are executed before the select statements, therefore the alias upvotes_count is not yet defined. I am using Postgres. Does this only work for MySQL? Is there a way around this other than having to do a havingRaw to manually get the count again?
@Stetzon withCount('upvotes') should add upvotes_count, so you should add this, or if you still have this problem, send me the query and i will check it.
@Stetzon Remember that you cannot do where clauses on aggregated columns, You can however do having clauses, so make sure that you are not doing where there.
I also have an error that the column doesn't exist with MySQL.
Same here, "Undefined column: 7 ERROR: column "users_count" does not exist". The thing is, "having()" is producing the error, "orderBy" works.
36

another good way to do this we can filter that separately and even assign an alias to that column name

$posts = Post::withCount([ 'upvotes', 'upvotes as upvotes_count' => function ($query) { $query->where('upvotes_count', '>', 5); }]) ->get(); 

Now in blade you can do

$posts->upvotes_count 

1 Comment

Isn't 'upvotes as upvotes_count' enough, do we really need to have 'upvotes', in array passed to withCount(...)method?
10

I'm not sure if this was implemented after your question, but you can now do it like this

$posts = Post::has('upvotes','>',5)->get(); 

Comments

7

I think using has() is the best solution:

Post::has('upvotes','>',5)->withCount('upvotes')->get() 

You could also use a filter:

Post::withCount('upvotes')->get()->filter(function($post) { return $post->upvotes_count > 5; }) 

You could also disable strict mode in config/database.php (probably not a good idea)

'strict' => false, Post::withCount('upvotes')->having('upvotes_count','>',5)->get() 

You could also try to add a groupBy clause (using having in strict mode), but this will likely require you to include every column in your table (due to 'ONLY_FULL_GROUP_BY'), which could break things if you ever add another column to your table, and probably won't work anyway because I think you need to include 'upvotes_count' in the groupBy and it seems to be a non grouping field.

Comments

3

If you need to select only rows that the counter is greater than or equal to 1 you can try the following code:

$posts = Post::withCount('upvotes') ->havingRaw('upvotes_count') ->get(); 

I don't know if this is the best solution but it's an alternative. Another alternative would be get the posts and use array filter as mentioned in a comment above.

Comments

1

I ran into the same problem, and tried the same things you did. I'm guessing there is a way to replicate the SQL generated by the withCounts call but add a way to make xxx_counts available to a where clause, but I just filtered the resulting collection instead.

$allTags = Tag::withCount('articles')->get(); $usedTags = $allTags->filter(function ($value, $key) { return $value->articles_count > 0; }); 

1 Comment

It's been quite a time, and as I learnt more about sql, you can't do where clauses on the aggregate functions, hence upvotes_count column isn't found since it's aggregated and not selected. but the above problem can be solved using some advanced queries and grouping them together.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.