Query builder GROUP BY, HAVING, COUNT in Laravel - mysql

how to express this code in query builder. I'm using Laravel 6.
SELECT * FROM feedback GROUP BY noTicket having count(`status`) < 2
My Code:
$feedback = DB::table('feedback')
->groupBy('noTicket')
->having('count(status)', '<', 2)
->get();
Error Code:
SQLSTATE[42000]: Syntax error or access violation: 1055 'sifora.feedback.idFeedback' isn't in GROUP BY
(SQL: select * from `feedback` group by `noTicket` having `count(status)` < 2)
What is wrong with my code? It seems match between sql code vs query builder.
Thank you

This is the working version of query
select noTicket
from feedback
group by noTicket
having count(status) < 2;
This is the query builder;
return DB::table('feedback')
->groupBy('noTicket')
->having(DB::raw('count(status)'), '<', 2)
->pluck('noTicket'); // you may replace this with get()/select()

$feedback = DB::table('feedback')
->selectRaw('feedback.*, count(status) as count_status')
->groupBy('noTicket')
->havingRaw('count(status) > ?', [2])
->get();
Also there exists strict mode, you can disable it in config/database.php
'connections' => [
'mysql' => [
'strict' => false
]
]
But I don't recommend to you to do it. Check this https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html here you get more info how group by works.

Here the complete code. Thanks a lot to Ersoy
$getArray = DB::table('feedback')
->groupBy('noTicket')
->having(DB::raw('count(status)'), '<', 2)
->pluck('noTicket');
$feedback = DB::table('feedback')
->whereIn('noTicket', $getArray)->get();

Related

How to Convert SQL Query to Eloquent Laravel

MY SQL Query:
SELECT * ,COUNT(posts_id) as `view `FROM `post_view` JOIN posts ON post_view.posts_id = posts.id
GROUP BY
posts_id
My Eloquent Laravel:
$this->model->Join('posts','post_view.posts_id', '=', 'posts.id')
->selectRaw('*, count(posts_id) as view')
->groupBy('posts_id')
->get();
Error when Get by Postman:
SQLSTATE[42000]: Syntax error or access violation: 1055 'databasePost.post_view.id' isn't in GROUP BY
(SQL: select *, count(posts_id) as view from `post_view` inner join `posts` on `post_view`.`posts_id` =
`posts`.`id` group by `posts_id`)
This error occurs because group by requiring all columns, is the speed of the query.
I think you are using a MySQL server with version 5.7.5+.
Check this out: MySQL Handling of GROUP BY
Method 1:
Use ANY_VALUE to the column or disable mysql mode:ONLY_FULL_GROUP_BY.
->selectRaw('ANY_VALUE(post_view.id), ... count(posts_id) as view')
->groupBy('posts_id')
PS: post_view.id and posts.id both named id, select them all out that one of them will be covered.
Method 2:
edit your applications's database config file config/database.php
In mysql array, set strict => false to disable MySQL's strict mode:
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
...
'strict' => false,
],

SQL Query GROUP BY Issue in Laravel Query Builder

I wrote the following MySQL query to get inbox messages of a user with each user and also with last message...
select *, `chat_channel` as `channel`, MAX(id) as max_id from `messages`
where (`message_to` = 2 or `message_from` = 2)
and (`delete_one` <> 2 and `delete_two` <> 2)
group by `channel`
order by `max_id` desc limit 40 offset 0
Laravel Method which I use...
public static function getInboxMessages($user_id, $limit = 40, $offset = 0, $search_key = null)
{
return Message::hasSearch($search_key)->select("*", DB::raw("MAX(id) as max_id"))->where(function ($sql) use (
$user_id
) {
$sql->where('message_to', '=', $user_id);
$sql->orWhere('message_from', '=', $user_id);
})->where(function ($sql) use ($user_id) {
$sql->where('delete_one', '<>', $user_id);
$sql->where('delete_two', '<>', $user_id);
})->with([
'sender' => function ($q) {
$q->select('id', 'uid', 'username', 'full_name', 'picture');
}
])->with([
'receiver' => function ($q) {
$q->select('id', 'uid', 'username', 'full_name', 'picture');
}
])->orderBy('max_id', 'DESC')->groupBy('chat_channel')->offset($offset)->limit($limit)->get();
}
However, when I run this query in phpMyAdmin I encounter the following error...
1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db.messages.id' which is not
functionally dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by
When I run Laravel code directly then I don't receive any error but I do get the records ordered by as expected.
Go to phpMyAdmin -> YourDB -> SQL Tab
Use following command :
SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY';
this will enable only full group by for your sql.
To revert the above command changes use :
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
it's the STRICT MODE of mysql for aggregation.
take notice that when you group by something and you select another non aggregated field, the value of that field is not correct 100%. aggregated field are those like the fields you are grouping by, count(field), sum(field),...etc
if you are willing to take that risk, go to config\database.php and edit the strict => true to false
'prefix' => '',
'strict' => false,
'engine' => null,
it is not recommended, and you should rework your query with a join on a group by select
select x from table right join (select gb from table group by gb) as grouped on grouped.gb = table.gb
something like this

SQL raw query in laravel query builder

I have a working SQL query.
SELECT stuid,grade,SUM(full_amount) FROM due_payments group by stuid having SUM(full_amount) !=15600
This is working fine in MySQL workbench and phpmyadmin,But i cant seems to get this work in Laravel 5.3
I tried this on Laravel app with no Luck
$someVariable = Input::get(15600);
$results = DB::select( DB::raw("SELECT stuid,grade,SUM(full_amount) FROM due_payments
group by stuid having SUM(full_amount) =:somevariable)", array(
'somevariable' => $someVariable,
)));
Can someone Help me with this.Thank You.
First if all Input::get() doesn't take value as argument but the element name
$someVariable = Input::get(15600);
You can just use $someVariable = 15600;
Then use Query Builder rather than Raw SQL query
$results = DB::table('due_payments')
->select(array('stuid', 'grade', DB::raw('SUM(full_amount)')))
->groupBy('stuid')
->havingRaw('SUM(full_amount) != '.$someVariable)
->get();
Use query builder.
$results = DB::table('due_payments')
->select('stuid', 'grade',DB::raw('SUM(full_amount)'))
->groupBy('stuid')
->havingRaw('SUM(full_amount) != 15600')
->get();

how to convert this simple sql query to doctrine querybuilder

I'm using php doctrine, and i can't convert this sql query to querybuilder .
i have problems with "group by"
any help please ?
SELECT * FROM message WHERE sender_id='2' OR receiver_id = '2' Group By (if(sender_id > receiver_id, sender_id, receiver_id)) , (if(sender_id <= receiver_id, sender_id,receiver_id)) Order BY createdAt DESC
this is what i did but i need condition on groupby
$queryBuilder = $this->createQueryBuilder('m');
$queryBuilder->where('m.sender = :user or m.receiver =:user')
->groupBy('m.sender','m.receiver')
->orderBy('m.createdAt', 'Desc')
->setParameter('user', $user);
This should probably work:
$qb = $this->createQueryBuilder('m');
$qb->where($qb->expr()->orX(
$qb->expr()->eq('m.sender', ':user'),
$qb->expr()->eq('m.receiver', ':user')
))->groupBy('m.sender')
->addGroupBy('m.receiver')
->orderBy('m.createdAt', 'DESC')
->setParameter('user', $user);
So apart from factoring out your where statement into relevant expr() statements (documentation) the only other change is splitting your groupBy into groupBy and then addGroupBy. You can do the same if you ever need to order by more than one things (orderBy and addOrderBy).

cakephp field() query error

I am trying to extract the latest id of the table called gal_providers
//get the id of the last gal_provider add.
$order = array("GalProvider.id DESC");
$gal_provider_id = $this->GalProvider->field("id",array("order"=>$order));
$this->data["User"]["username"] = "gal_provider_".$gal_provider_id;
But it shows error like :
Warning (512): SQL Error: 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 'order = ('GalProvider.id DESC') LIMIT 1'
at line 1 [CORE/cake/libs/model/datasources/dbo_source.php, line 684]
Query: SELECT GalProvider.id FROM gal_providers AS GalProvider
WHERE order = ('GalProvider.id DESC') LIMIT 1
Whats wrong with the code ?
try to change this:
$order = array("GalProvider.id DESC");
to this:
$order = array('GalProvider.id' => 'desc');
or try this:
$gal_provider_id = $this->GalProvider->field("id",array('order' => array('GalProvider.id' => 'desc')));
As noted in the CakePHP documentation, the second argument of the Model::field() method is for a condition, and the third is for the order.
Also looking at the documentation, we can see that by default the condition and order arguments are null - which means we can do the same.
Try this:
$gal_provider_id = $this->GalProvider->field("id", null, "id DESC");
$this->data["User"]["username"] = "gal_provider_".$gal_provider_id;
In your example, you're using the Model::field() method as if it were the Model::find() method (they are two different methods and require different formats for their arguments)
Alternatively, we can use the find method itself:
$gal_provider = $this->GalProvider->find('first', array(
'fields' => array('GalProvider.id'),
'order' => 'GalProvider.id DESC',
'recursive' => -1 // more efficient (ensures no joins made for the query)
));
$this->data["User"]["username"] = "gal_provider_".$gal_provider['GalProvider']['id'];