How do you convert this raw sql builder to laravel DB Builder
SELECT *
FROM `applications`
WHERE EXISTS (SELECT *
FROM `applicants`
INNER JOIN `applicant_application`
ON `applicants`.`id` =
`applicant_application`.`applicant_id`
WHERE `applications`.`id` =
`applicant_application`.`application_id`
AND `user_id` = 18)
ORDER BY `created_at` DESC
LIMIT 20
This is what I've tried but doesn't seem to work
DB::table('applications as apt')
->whereExists( function ($q) {
$q->from('applicants as app')
->join('applicant_application as aa', 'app.id', '=', 'aa.applicant_id')
->where('apt.id', '=', 'aa.application_id')
->where('app.user_id', '=', 18);
})->orderBy('created_at', 'DESC')->paginate(10);
Would appreciate any help
Because apt.id and aa.application_id are two columns from diff tables, and you are using where to compare the apt.id with string 'aa.application_id'.
You need to use whereColumn to compare two different columns:
->whereColumn('apt.id', '=', 'aa.application_id')
Related
I have a complex query with a correlated subquery which I would like to integrate in my Laravel application.
The problem is that the subquery is inside IFNULL.
The query is very big, I tried to write a very reduced one only for demonstration:
SELECT payment_status_id, client_tbl.client_id
IFNULL((SELECT payment_status_id
FROM payment_status_tbl
WHERE payment_status_tbl.client_id = client_tbl.client_id
ORDER BY status_date DESC
LIMIT 1), 0) AS current_status_id
FROM client_tbl
HAVING current_status_id < 4;
I reached this query in Laravel:
$query = DB::table('client_tbl')
->select(['payment_status_id', 'client_tbl.client_id'])
->selectSub(function($query) {
$query->select('payment_status_id')
->from('payment_status_tbl')
->where('payment_status_tbl.client_id', '=', 'client_tbl.client_id')
->orderByDesc('status_date')
->limit(1);
}, 'current_status_id')
->having('current_status_id', '<', 4);
but it does not include the IFNULL statement, which is important in my original query.
Any idea whether it is possible?
Try this
$query = DB::table('client_tbl')
->select(['payment_status_id', 'client_tbl.client_id'])
->selectSub(function($query) {
$getId = DB::table('payment_status_tbl')
->where('payment_status_tbl.client_id','`client_tbl.client_id`')
->select('payment_status_id')
->orderBy('status_date','DESC')
->first();
$query->empty($getId)? 0 : $getId->payment_status_id;
}, 'current_status_id')
->having('current_status_id', '<', 4);
I get 3 tables in my database. I want to know how to translate this mysql query in laravel. Here is the code:
SELECT item.id, item.libelle, entre.item_id, entre.total AS etotal, entre.prix_unitaire AS eprix, sortie.total AS stotal, sortie.prix_unitaire AS sprix, (entre.total - sortie.total) AS restant
FROM (
SELECT id, libelle
FROM items
WHERE EXISTS (
SELECT *
FROM entrees
WHERE items.id = entrees.item_id
AND date_entree = '23-10-2019'
)
) item
LEFT JOIN (
SELECT item_id, prix_unitaire, sum(total) total
FROM entrees
WHERE date_entree = '23-10-2019'
GROUP BY item_id
) entre ON item.id = entre.item_id
LEFT JOIN (
SELECT item_id, prix_unitaire, sum(total) total
FROM sorties
GROUP BY item_id
) sortie ON entre.item_id = sortie.item_id;
For table entrees enter image description here
For table items enter image description here
For table sortiesenter image description here
So please help me. And if possible explain me the query cause honestly I found it on another forum
First let's break down your query into all the subqueries and then write them all together.
Subquery 1
SELECT id, libelle
FROM items
WHERE EXISTS (
SELECT *
FROM entrees
WHERE items.id = entrees.item_id
AND date_entree = '23-10-2019'
)
Translated to Query Builder:
$subquery1 = DB::table('items')
->select('id', 'libelle')
->whereExists(function ($query) {
$query->from('entrees')
->whereColumn('items.id', 'entrees.item_id')
->where('date_entree', '23-10-2019');
});
// You can verify this by dumping $subquery1->toSql() in the console.
Subquery 2
SELECT item_id, prix_unitaire, sum(total) total
FROM entrees
WHERE date_entree = '23-10-2019'
GROUP BY item_id
Translated to Query Builder:
$subquery2 = DB::table('entrees')
->select('item_id', 'prix_unitaire')
->selectRaw('sum(total) as total')
->where('date_entree', '23-10-2019')
->groupBy('item_id');
// You can verify this by dumping $subquery2->toSql() in the artisan console.
Subquery 3
SELECT item_id, prix_unitaire, sum(total) total
FROM sorties
GROUP BY item_id
Translated to Query Builder:
$subquery3 = DB::table('sorties')
->select('item_id', 'prix_unitaire')
->selectRaw('sum(total) as total')
->groupBy('item_id');
// You can verify this by dumping $subquery3->toSql() in the artisan console.
Now, to put it all together:
$query = DB::table($subquery1, 'item')
->select(
'item.id',
'item.libelle',
'entre.item_id',
'entre.total as etotal',
'entre.prix_unitaire as eprix',
'sortie.total as stotal',
'sotrie.prix_unitaire as sprix'
)
->selectRaw('(entre.total - sortie.total) as restant')
->leftJoinSub($subquery2, 'entre', function ($join) {
$join->on('item.id', '=', 'entre.item_id');
})
->leftJoinSub($subquery3, 'sortie', function ($join) {
$join->on('entre.item_id', '=', 'sortie.item_id');
});
// You can verify this by dumping $query->toSql() in the artisan console.
// To get the results, simply append the ->get() to the $query or do $query->get();
Below is a screen capture of this code being tested in the artisan console. The reason I'm using $db-> instead of DB:: is because I ran the following line before:
$db = DB::connection('mysql');
which makes sure the query is translated to mysql when I use toSql(). Pay it no mind.
Everything I used can be found in the official documentation about queries.
Here is my sql, i am struggling to translate this to laravel 5.8 query builder syntax.
SELECT CC AS CountOfVisits, Count(CC) AS Users
FROM
(
SELECT user_id, count(user_id) AS CC FROM mytable
GROUP BY user_id
) AS CC
GROUP BY CC;
I tried this:
$frequency= DB::connection('mysql2')
->select(DB::raw('CC AS CountOfVisits'), DB::raw('Count(CC) AS Users'))
->from(function($sq)
{
$sq->select(DB::raw('user_id, count(user_id) AS CC FROM '))
->from('mytable')
->groupBy('user_id');
})
->groupBy('CC')
->get();
it errors with
Argument 1 passed to Illuminate\Database\Connection::prepareBindings()
must be of the type array, object given, called in
/var/app/portal/vendor/laravel/framework/src/Illuminate/Database/Connection.php
on line 665
Any help would be great thanks
I think the problem you're having is that the returned connection is expecting string for the full query with additional bindings on the second parameter. You can still build it using illuminate's query builder first if you like, then run the select using the generated string.
$query = DB::query()
->select('CC AS CountOfVisits', DB::raw('count(CC) AS Users'))
->fromSub(function (\Illuminate\Database\Query\Builder $query) {
$query->select('user_id', DB::raw('count(user_id) AS CC '))
->from('mytable')
->groupBy('user_id');
}, 'CC')
->groupBy('CC');
$result = DB::connection()->select($query->toSql());
When DataTables tries to get data, it always gets tripped up on this Eloquent query:
$items = Item::select([
DB::raw("images.url AS image"),
'items.id',
'items.sku',
'items.quantity',
DB::raw("IF(items.enabled, 'Yes', 'No') AS enabled")
])
->leftJoin('images', function ($j) {
$j->on('images.imageable_id', '=', 'items.id')
->where('images.imageable_type', '=', 'Item');
})
->leftJoin('order_items', 'items.id', '=', 'order_items.item_id')
->leftJoin('orders', 'orders.id', '=', 'order_items.order_id')
->where('items.store_id', 1)
->whereNull('items.deleted_at')
->whereIn('items.status', ['active', 'submitted'])
->groupBy('items.id');
The query works just fine as is and returns the desired results. However, DataTables tries to transform it into the following which produces the error:
select count(*) as aggregate from (select '1' as row from `items` left join `images` on `images`.`imageable_id` = `items`.`id` and `images`.`imageable_type` = 1 left join `order_items` on `items`.`id` = `order_items`.`item_id` left join `orders` on `orders`.`id` = `order_items`.`order_id` where `items`.`store_id` = 1 and `items`.`deleted_at` is null group by `items`.`id`) AS count_row_table
This produces this error specifically:
SQLSTATE[HY093]: Invalid parameter number
/home/vagrant/Projects/test.dev/vendor/laravel/framework/src/Illuminate/Database/Connection.php#301
When I execute that query directly on the MySQL database, it has no problem. This seems to be happening within Laravel only.
If I remove the ->leftJoin('images', function ($j) {...} part of the query then there is no error, but I need that join for the image.
How to get around this error?
Full error output returned to DataTables over AJAX:
{
"error":{
"type":"Illuminate\\Database\\QueryException",
"message":"SQLSTATE[HY093]: Invalid parameter number (SQL: select count(*) as aggregate from (select '1' as row from `items` left join `images` on `images`.`imageable_id` = `items`.`id` and `images`.`imageable_type` = 1 left join `order_items` on `items`.`id` = `order_items`.`item_id` left join `orders` on `orders`.`id` = `order_items`.`order_id` where `items`.`store_id` = active and `items`.`deleted_at` is null and `items`.`status` in (submitted, ?) group by `items`.`id`) AS count_row_table)",
"file":"\/home\/vagrant\/Projects\/test.dev\/vendor\/laravel\/framework\/src\/Illuminate\/Database\/Connection.php",
"line":625
}
}
I have had a similar issue today, not with DataTables but with a complex query being built using the standalone query builder. The issue was similar to yours with the left join, passing a closure to build a more complex join condition. I was using a where condition after the "on".
The solution was to chain "on" calls:
->leftJoin('images', function ($j) {
$j->on('images.imageable_id', '=', 'items.id')
// note the "on" rather than the "where" and the use of a raw statement
->on('images.imageable_type', '=', DB::raw('Item'));
})
I had this exact issue. The work around is not perfect since it will basically grab all the data twice, but it's the only way I could get it to work.
You have to do a ->get(); before sending it to ->make();. I honestly hope someone finds the right solution but for now:
Temp solution:
$data = DB::table('some_table');
$data->leftJoin('some_other_table', function($join)
{
$join->on('some_table.id', '=', 'some_other_table.id')
->where('some_table.something', '=', 'some_value');
});
$data->get();
return Datatables::of($data)->make();
This is with using the datatables package for Laravel: https://github.com/bllim/laravel4-datatables-package
I am trying to convert a MYSQL query to codeigniter and going no wheres real fast. I am trying to convert this query
$conn->prepare("SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = (SELECT MAX(mix_number) FROM podcasts) order by track asc");
This is in my model:
//$where = '(SELECT MAX(mix_number)from podcasts)';
$this->db->select('id,song,artist,album,track,mix_name,date, link');
//$this->db->where('mix_number', '(SELECT MAX(mix_number)from podcasts)');
$this->db->order_by('track', 'asc');
$query = $this->db->get('podcasts');
return $query->result();
My problem area is in the where statement. When I comment out the where statement I get the data. Obviously not in the manner I want it.
I am doing it this way becuase my next query(s) will be
("SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = **(SELECT MAX(mix_number) FROM podcasts) - 1** order by track asc")
And on down to (SELECT MAX(mix_number) FROM podcasts) - 3
Any thoughts on the proper way of writing the where statement? Thank you for yout time.
Set the third argument of where() to false to prevent CI from altering the string you pass in to the second argument, then you can do the subquery:
return $this->db
->select('id,song,artist,album,track,mix_name,date, link')
->where('mix_number', '(SELECT MAX(mix_number) from podcasts)', false)
->order_by('track', 'asc')
->get('podcasts')
->result();
https://www.codeigniter.com/userguide2/database/active_record.html$this->db->where() accepts an optional third parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names with backticks.
For me this produces the following query:
SELECT `id`, `song`, `artist`, `album`, `track`, `mix_name`, `date`, `link`
FROM (`podcasts`)
WHERE mix_number = (SELECT MAX(mix_number) from podcasts) ORDER BY `track` asc
If you are not too particular about using CodeIgniter's Active Record syntax, you can simply use your query as is:
$sql = "SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = (SELECT MAX(mix_number) FROM podcasts) order by track asc";
$this->db->query($sql);
and then use $query->result() to get your results.