#1054 - Unknown column with backticks - mysql

I get 1054 - Unknown column error when I use backticks in where clause with mysql
`roles`.`id`
but it works fine with
'roles.id'
Any idea why and how to solve it? I need to make it work with backticks to make use of the Laravel Eloquent query builder.
select *
from `users` inner join `role_user` on `users`.`id` = `role_user`.`user_id`
where `roles`.`id` = `role_user`.`role_id` and (`users`.`id` = 8) and `users`.`id` = 8
Laravel - Eloquent query:
Policy::whereHas('role.users', function ($query) use ($user_id) {
$query->where([
'users.id' => $user_id
])->get();
});

As stated by #Barmar my query was missing a roles table in the FROM or JOIN clauses.
Since I have this error because the query was generated from Laravel - Eloquent I am posting my solution for future reference.
Policy::whereHas('role.users', function ($query) use ($user_id) {
$query->where([
'users.id' => $user_id
]);
})->get();
The problem was because I misplaced the get in the query builder inside whereHas instead of the outermost the query builder.

Related

Laravel duplicates join on production

I have a code where Eloquent query builder joins the ManyToOne tables articles and users.
The code looks like:
$model = Article::with('user')->select('articles.*'));
and then the model filters the user name
$model = $model->join('users', 'articles.user_id', '=', 'users.id')
->where('users.name', 'like', "%$value%");
This throws me an error:
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique
table/alias: 'users' (SQL: select count(*) as aggregate from
articles inner join users on articles.user_id = users.id
inner join users on articles.user_id = users.id where
users.name like %may% and users.name like %may% and
articles.deleted_at is null)
Look at the duplicate inner join on users table and also duplicate where clause.
The same code on localhost works fine and create sql:
select count(*) as aggregate from `articles` inner join `users` on `articles`.`user_id` = `users`.`id` where `users`.`name` like '%may%' and `articles`.`deleted_at` is null
Original code is here: https://github.com/camohub/laravel-datagrid-example/blob/master/app/Http/Controllers/DefaultController.php#L25
and the live error is here: https://laravel-datagrid.tatrytec.eu/?chgrid-filter-username=may&chgrid-perPage=25
I dont understand. It looks like some database setting is wrong.
Hope somebody knows what happened there. Thanks a lot.
EDIT: The issue is caused by PHP version. Production is lower 7.4.3 than localhost 7.4.19
The solution is to write an envelope above the Eloquent query builder. Here it is https://github.com/camohub/laravel-datagrid/blob/master/src/QueryBuilder.php

converting from simple mysql to Laravel query constructor

#forpas guys, I need to the query into laravel constructor.
this is what I tried.
$cates = DB::table('categories')
->select(DB::raw('categories.category_id, categories.category_title, categories.created_at, COUNT(task.task_id) AS counted_tasks'))
->leftJoin('tasks', 'categories.category_id', '=', 'tasks.task_cat_id')
->get();
Illuminate\Database\QueryException
SQLSTATE[42000]: Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause (SQL: select categories.category_id, categories.category_title, categories.created_at, COUNT(task.task_id) AS counted_tasks from categories left join tasks on categories.category_id = tasks.task_cat_id)
Where I can see the final query of the constructor?
You're missing the groupBy. Try this code below:
$cates = DB::table('categories')
->select(DB::raw('categories.category_id, categories.category_title, categories.created_at, COUNT(task.task_id) AS counted_tasks'))
->leftJoin('tasks', 'categories.category_id', '=', 'tasks.task_cat_id')
->groupBy('categories.category_id, categories.category_title, categories.created_at')
->get();

Laravel 5.3 query builder access violation on group by

I have been using Laravel 5 for a week and I've now come to the point where I want to convert all my existing raw SQL queries using Query Builder but I have a problem.
When I run the following query, I get this error message
SQLSTATE[42000]: Syntax error or access violation: 1055
'procurement.pp_proposals.title' isn't in GROUP BY
$proposals = DB::table('tableA')
->join('tableB', 'tableA.id', '=', 'tableB.id')
->leftJoin('tableC', 'tableA.id', '=', 'tableC.id')
->select(DB::raw('tableA.id, title, date_created, date_completed, percent_complete, complete, COALESCE(COUNT(tableC.id), 0) AS total_ids'))
->where([
['tableB.user', '=', Auth::user()->username],
['submitted', '=', '0'],
])
->groupBy('tableA.id')
->orderBy('title', 'asc')
->get();
This is my raw SQL that works perfectly fine so I don't understand why i need to GROUP BY on all the extra columns
SELECT tableA.id,
title,
date_created,
date_completed,
percent_complete,
complete,
COALESCE(COUNT(tableC.id), 0) AS 'total_ids'
FROM tableA
INNER JOIN tableB
ON tableA.id = tableB.id
LEFT JOIN tableC
ON tableA.id = tableC.id
WHERE submitted = '0' AND tableB.user = 'user'
GROUP BY tableA.id
ORDER by title ASC
I am not sure how it works but surely you can fix that issue by setting strict = false on the config/database.php file to your MySQL config!
I had the same issue and setting it to false solve my problem!
Actually I just opened a question here to find why it happens!
If you want to follow: Strict database config Laravel 5.2 to Laravel 5.3

Need a SQL to Laravel Eloquent Translation

I need to translate the following SQL query into Laravel's Eloquent syntax:
SELECT a.*
FROM applications a
LEFT JOIN ratings r
ON a.id = r.application_id
AND r.admin_id = 1
WHERE r.admin_id IS NULL
The only way I've been able to get it to work is running the query using DB::raw, but I'm curious how it should look when using the Eloquent syntax. Ideally, I'd like to be able to migrate to any other database without a hiccup.
You can pass a closure to a join. You need to use DB::raw() as you're specifying a variable, rather than another database column to join on.
DB::table('applications')
->select('applications.*')
->leftJoin('ratings', function($join)
{
$join->on('ratings.application_id', '=', 'applications.id');
$join->on('ratings.admin_id', '=', DB::raw('1'));
})
->whereNull('ratings.admin_id')
->get()

How do I take the last so many entries (skip) with Eloquent Query Builder in Laravel

I am trying to write a query in Laravel using Eloquent, but only want the last 5-ongoing fields in it. This is the query:
public static function past_profile_fan_likes($id) {
$latest_profile_fan_likes = DB::table('fanartists')
->join('artists', 'fanartists.artist_id', '=', 'artists.id')
->orderBy('fanartists.created_at', 'DESC')
->skip(4)
->where('fanartists.fan_id', '=', $id)
->select('artists.id', 'artists.fbid', 'artists.stage_name', 'artists.city', 'artists.state', 'artists.image_path', 'artists.description')
->get();
return $latest_profile_fan_likes;
}
When I call this, I am getting this error:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'offset 4' at line 1 (SQL: select `artists`.`id`, `artists`.`fbid`, `artists`.`stage_name`, `artists`.`city`, `artists`.`state`, `artists`.`image_path`, `artists`.`description` from `fanartists` inner join `artists` on `fanartists`.`artist_id` = `artists`.`id` where `fanartists`.`fan_id` = ? order by `fanartists`.`created_at` desc offset 4) (Bindings: array ( 0 => '1', ))
Is there something I am doing wrong here? Maybe something wrong with the skip usage? Thanks for your help.
You need to add a take query in order for it to add a LIMIT query and turn it into the correct syntax;
DB::table('fanartists')
->join('artists', 'fanartists.artist_id', '=', 'artists.id')
->orderBy('fanartists.created_at', 'DESC')
->skip(4)
->take(100)
->where('fanartists.fan_id', '=', $id)
->select('artists.id', 'artists.fbid', 'artists.stage_name', 'artists.city', 'artists.state', 'artists.image_path', 'artists.description')
->get();
You will need to suppliy a limit if using an offset, even if you don't want to limit. See here: http://dev.mysql.com/doc/refman/5.0/en/select.html#id4651990
This looks more like fluent which I'm not quite as familiar with. but if you have your models and relationships defined, using Eloquent, you could reverse the order and take(5) if you're just looking to get the last 5 records:
like this...
$latest_profile_fan_likes = fanartists::with('artists')->where('fan_id', '=', $id)->orderBy('created_at', 'ASC')->take(5)->get('id', 'fbid' .......);