running mysql query on Laravel `DB::Raw` - php

I have a MYSQL query that i need to run on Laravel 5.6 query builder. my query is
SELECT paper_id,user_id,COUNT(payments.user_id),users.district
FROM payments
LEFT JOIN users ON payments.user_id = users.id
WHERE payments.paper_id=3
GROUP BY users.district HAVING COUNT(payments.user_id)>=0;
I have tried running this on Laravel DB::Raw with this code
$data=DB::Raw('SELECT paper_id,user_id,COUNT(payments.user_id),users.district
FROM payments
LEFT JOIN users ON payments.user_id = users.id
WHERE payments.paper_id='.$paper_id.'
GROUP BY users.district HAVING
COUNT(payments.user_id)>=0
');
as well as through this code
$data2=DB::table('payments')
->leftJoin('users','payments.user_id','users.id')
->select('paper_id','user_id','users.district',
DB::Raw('COUNT(payments.user_id)'))
->where('payments.paper_id',$paper_id)
->groupBy('users.district')
->select(DB::Raw('HAVING COUNT(payments.user_id)>=0'))
->get();
Error I get on $data (first query) query
[{}]
i get an empty response
Error I get on `$data2 (second query) query
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error
in your SQL syntax; check the manual that corresponds to your MariaDB server
version for the right syntax to use near 'HAVING COUNT(payments.user_id)>=0 from
payments left join users on payments at line 1 (SQL: select HAVING
COUNT(payments.user_id)>=0 from payments left join users on
payments.user_id = users.id where payments.paper_id = 1 group by
users.district)
But i get SQL syntax error can someone please let me know how to convert SQL to Laravel query builder format.

Running Raw SQL Queries
$data = DB::select('SELECT paper_id,user_id,COUNT(payments.user_id),users.district
FROM payments
LEFT JOIN users ON payments.user_id = users.id
WHERE payments.paper_id= ?
GROUP BY users.district HAVING
COUNT(payments.user_id)>=0', [$paper_id]);
Parameter binding provides protection against SQL injection.
https://laravel.com/docs/5.6/database#running-queries
groupBy / having
->select(DB::Raw('HAVING COUNT(payments.user_id)>=0'))
=>
->having(DB::Raw('COUNT(payments.user_id)'), '>=', 0)
https://laravel.com/docs/5.6/queries#ordering-grouping-limit-and-offset

Try This:
When use Raw query
$data = DB::select('SELECT paper_id,user_id,COUNT(payments.user_id),users.district
FROM payments
LEFT JOIN users ON payments.user_id = users.id
WHERE payments.paper_id='.$paper_id.'
GROUP BY users.district HAVING
COUNT(payments.user_id)>=0
');
OR
$data2= DB::table('payments')->select([
'payments.paper_id','payments.user_id','users.district',
DB::Raw('COUNT(payments.user_id)')
])
->leftJoin('users','payments.user_id','users.id')
->where('payments.paper_id',$paper_id)
->havingRaw("COUNT(payments.user_id)>=0")
->groupBy('users.district')
->get();
I think select function should use one time only in a query, No need to add multiple time. And before add any questin alway search about your problem. Hope it will work..
For your error
SQLSTATE[42000]: Syntax error or access violation: 1055
In this file
vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php
at this location in your laravel replace this file this for laravel5.4
PDO::ATTR_EMULATE_PREPARES => true,

Related

How to Translate Codeigniter Pre Formatted Query Into an Original Mysql Query (e.g $this->db->select('table1.*,table2.*,table3.*'))

I have a website which is using a CodeIgniter framework and almost using CodeIgniter's preformatted query class in every request to process data from database built by my ex coworker.
One of the example is like this:
function tampilkan_data(){
$this->db->select('barang.*,barang_keluar.*,barang_masuk.*');
$this->db->from('barang');
$this->db->join('barang_keluar', 'barang.id_barang=barang_keluar.id_barang','left');
$this->db->join('barang_masuk', 'barang.id_barang=barang_masuk.id_barang','left');
$this->db->order_by('barang.id_barang','asc');
$this->db->order_by('barang.kode_barang','asc');
$this->db->where('barang.status','0');
return $query = $this->db->get()->result();
}
I want to change the result from that query, but in order to understand it first I have to translate it into an original MySQL query. Attempted to do this:
SELECT `barang`.*, `barang_keluar`.*, `barang_masuk`.*
FROM `barang` AS A
LEFT JOIN `barang_keluar` AS B ON A.id_barang = B.id_barang
LEFT JOIN `barang_masuk` AS C ON A.id_barang = C.id_barang
ORDER BY A.id_barang ASC, A.kode_barang ASC
WHERE A.status = 0
But I got this 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 'WHERE A.status = 0 LIMIT 0, 25' at line 6
I tried to remove the WHERE A.status = 0 to see which is wrong from my code the I got this error
1051 - Unknown table 'barang'
I thought the problem is in the line SELECT barang.*, barang_keluar.*, barang_masuk.*, because I didn't really know how to write it in an MySQL original formatted.
I already searched for this topic and I even tried to write the query straight to the search bar but I didn't find the right approach according to my case.
Hope someone can help
You can simply print your query, Then you can see your query in original sql format.
function tampilkan_data(){
$this->db->select('barang.*,barang_keluar.*,barang_masuk.*');
$this->db->from('barang');
$this->db->join('barang_keluar', 'barang.id_barang=barang_keluar.id_barang','left');
$this->db->join('barang_masuk', 'barang.id_barang=barang_masuk.id_barang','left');
$this->db->order_by('barang.id_barang','asc');
$this->db->order_by('barang.kode_barang','asc');
$this->db->where('barang.status','0');
$query = $this->db->get()->result(); // notice that i have removed the return keyword
echo $this->db->last_query(); // This will print your query directly on the screen.
}
But the error which you are getting is -> You don't have a table named barang.
Make sure that the table exists.
Hope It Helps...
If you want to look at the query string generated by the CI Query builder then you can log this method $this->db->last_query() which will give the last SQL query as string executed by it.
Your query is almost ok. But you will have to change it on order by. Because u have used asc more than once, that is not supported by mysql as well. You need to modify your query like below
SELECT A.*, B.*, C.*
FROM barang AS A
LEFT JOIN barang_keluar AS B ON A.id_barang = B.id_barang
LEFT JOIN barang_masuk AS C ON A.id_barang = C.id_barang
WHERE A.status = 0 ORDER BY A.id_barang, A.kode_barang ASC
Now be confirm that you have table barang in your database and try again. If you face another sql problem just reply with your screenshot of code snippet here.

How to convert a sql which has a join within a left join to query builder?

I need to write a query builder from sql which has a join within a left join.
This is the SQL which has a join within another left join.
select v_dts.* from v_dts
left join(select in_d2.ref_book from in_h
inner join in_d2 on(in_h.doc_code=in_d2.doc_code and in_h.book=in_d2.book)
where in_h.doc_code='IN' group by in_d2.ref_book) as i
on(v_dts.book=i.ref_book)
(Problem)This is the Query Builder that I try to convert from the SQL above.
$order_progress = DB::table('v_dts')
->select('v_dts.*')
->leftJoin('in_h',function($join_in_h){
$join_in_h->select('in_d2.ref_book');
$join_in_h->join('in_d2',function($join_in_d2){
$join_in_d2->on('in_h.doc_code','=','in_d2.doc_code');
$join_in_d2->on('in_h.book','=','in_d2.book');
$join_in_d2->where('in_h.doc_code','=','IN');
$join_in_d2->groupBy('in_d2.ref_book');
});
})
->get();
However, my query builder is wrong.
It show an error message
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
and generated SQL
SQL: select v_dts.* from v_dts left join (in_h inner join in_d2 on in_h.doc_code = in_d2.doc_code and in_h.book = in_d2.book and in_h.doc_code = IN)
Anyone can help me to figure out my problem?
Thanks.
You need a subquery left join. ->leftJoin('in_h',function($join_in_h){...} does not do a subquery join; that's a regular left join with a fancy join clause.
Instead use ->leftJoinSub.
You may use the joinSub, leftJoinSub, and rightJoinSub methods to join a query to a sub-query. Each of these methods receive three arguments: the sub-query, its table alias, and a Closure that defines the related columns.
Write the subquery.
$ref_books = DB::table('in_h')
->select('in_d2.ref_book')
->join('in_d2', function($join){
$join->on('in_h.doc_code','=','in_d2.doc_code')
->where('in_h.book','=','in_d2.book');
})
->where('in_h.doc_code','=','IN')
->groupBy('in_d2.ref_book');
And use it in another query.
$order_progress = DB::table('v_dts')
->select('v_dts.*')
->leftJoinSub($ref_books, 'i',function($join){
$join->on('v_dts.book', '=', 'i.ref_book');
})
->get();
You can use ->dd() and ->dump() to dump the generated SQL for debugging.
See "Sub-Query Joins" in the Laravel docs.
Note: I don't have Laravel so I can't check this is 100% correct, but it should get you on the right path.

Laravel DB:select() requires all columns in the group by

I need to run a custom query and I have tried all these methods
$sql = "SELECT acd.*, DATE_FORMAT(acd.cdate, '%d/%m/%Y') cdate_disp,
GROUP_CONCAT(CONCAT_WS(', ', car.type, car.session, crd.name) SEPARATOR '<br />') rd_names,
acb.booking_status my_booking_status
FROM app_data acd
INNER JOIN crmaccounts ca ON ca.id = acd.client_crm_id
LEFT JOIN crmaccount_rdids car ON car.account_id = ca.id
LEFT JOIN crmrd_ids crd ON crd.id = car.rd_id
LEFT JOIN app_bookings acb ON acb.call_ref_id = acd.call_ref AND acb.user_id = 12391
WHERE 1=1
AND acd.client_crm_id NOT IN (select account_id from bstaff WHERE user_id=12391)
GROUP BY acd.id
ORDER BY acd.cdate, ctiming";
DB:select($sql);
throws
Illuminate \ Database \ QueryException (42000)
SQLSTATE[42000]: Syntax error or access violation: 1055 'mydatabase.acd.call_ref' isn't in GROUP BY (SQL: ....)
DB::select($sql);
DB::raw($sql);
DB::select(DB::raw($sql));
//even with pdo
$sth = DB::getPdo()->prepare($sql);
$sth->execute();
$data = $sth->fetchAll(\PDO::FETCH_OBJ);
PDOException (42000)
SQLSTATE[42000]: Syntax error or access violation: 1055 'mydatabase.acd.call_ref' isn't in GROUP BY
It seems like the only way to get working is to list all the table columns in the group by which is doable but not convenient.
I am able to run the same query directly in the phpmyadmin. So I am not sure why when I run it through Laravel it asks me add all columns.
I have MariaDB installed and both Laravel and PhpMyAdmin are connecting to the same instance. Larvel version is 5.8.5.
Please take a look at full query as I asked question here too but couldn't find any answer - https://laracasts.com/discuss/channels/eloquent/query-runs-ok-in-phpmyadmin-but-dbselect-throws-exception
You should try disabling the strict mode in config/database.php, in mysql connection section.
This is not a Laravel issue, but a logical limitation by MySQL. When you add columns to your results set that are not in the GROUP BY clause, different values could be possible for these columns in the result set.
When executing queries in strict mode (which is on by default), MySQL will not allow this because it could lead to unexpected results. If you turn off strict mode MySQL will use the first result it finds for these columns.
You can turn off strict mode in your Laravel config files in config/database.php. However, it is recommended to change your query instead because of the unpredictability.
A full list of checks in strict mode can be found in the MySQL documentation: https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sql-mode-strict
I have installed Laravel 4.8 and also configured Auth. further more,I add two tables called as role and states and tried your pdo code - its perfectly works for me! Here, I put my code.
$sql = "SELECT *
FROM users u
INNER JOIN roles r ON r.id = u.role_id
LEFT JOIN states s ON s.id = u.state_id
WHERE 1=1
GROUP BY u.id
ORDER BY u.id ";
$sth = DB::getPdo()->prepare($sql);
$sth->execute();
$data = $sth->fetchAll(\PDO::FETCH_OBJ);
dd($data);
I am eager to know what is your db structure.

Adding pagination to inner join-ed laravel

I am getting error on pagination
$writers = $writer::join('categories','categories.id','=','writers.category_id')
->where([['categories.category_name', '=', $category]])->paginate(1);
Can anyone tell how to paginate an inner join query.
This is the error message I'm getting:
QueryException in Connection.php line 770: 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 count(*) as aggregate from writers` inner join categories on categories.id = writers.category_id where (categories.category_name = Comic))
You need to specify GROUP_BY clause on your query
$writers = Writer::join('categories','categories.id','=','writers.category_id')
->where('categories.category_name', '=', $category)
->groupBy('writers.id')
->paginate(1);
UPDATE
If you still get an error, check your config/database.php. Be sure that in mysql settingsstrict = false
UPDATE 2
strict mode works on mysql starting from 5.7. If you have mysql under 5.7, set strict => false. You can check this link for more information:
Strict mode

Executing raw query in laravel 5.3

I am trying to execute some raw queries in laravel 5.3. the queries are simple but im getting errors.
table name: users
columns: id|name|email|phone|created_at|updated_at
my query:
SELECT created_at AS member_since, count(*) as row_count
FROM users
GROUP by MONTH(created_at);
This raw query works fine when I execute this on phpmyadmin. But when I execute this using laravel's database query builder i get error.
SQLSTATE[42000]: Syntax error or access violation: 1055
'query.users.created_at' isn't in GROUP BY
SQLSTATE[42000]: Syntax error or access violation: 1055
'query.users.created_at' isn't in GROUP BY (SQL: select created_at AS
member_since from `users` group by MONTH(created_at))
here is my controller:
$users = DB::table('users')
->select(DB::raw('created_at AS member_since', 'count(*) AS row_count'))
->groupBy(DB::raw('MONTH(created_at)'))
->get();
return response()->json($users);
Please correct me if Im wrong. Are there any better ways to execute raw queries?
First, you need to understand the error you're getting. This question is all about it https://stackoverflow.com/a/38551525/2474872
Now, with that in mind you have two choices
Disable only_full_group_bysetting.
Follow the indications provided
by the error message:
$users = DB::table('users')
->select(DB::raw('created_at AS member_since, count(*) AS row_count'))
->groupBy(DB::raw('MONTH(created_at)'), 'created_at')
->get();
groupBy(DB::raw('MONTH(created_at)'), 'created_at') can also be groupBy(DB::raw('MONTH(created_at), created_at')

Categories