Eloquent Subquery using models - laravel

i want to turn this raw sql to eloquent
SELECT x.* from
(SELECT * from clients where office_id IN(74,129,19)) AS x
where
x.firstname like '%parker%' or
x.lastname like '%parker%'
My model is Client

Okay i found out the answer using the
use Illuminate\Database\Eloquent\Builder;
$office_ids = [74,129,19];
Client::with('office')->whereIn('office_id',$office_ids)->where(function(Builder $dbQuery){
....
})

Related

How to use WITH clause in Laravel Query Builder

I have SQL query (see example).
But I can't find a way how I can write it in Query Builder.
Do you have any ideas how is it possible?
WITH main AS (
SELECT id FROM table1
)
SELECT * FROM table2
WHERE
table2.id IN (SELECT * FROM main)
I want to get format like:
$latestPosts = DB::table('posts')
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
->where('is_published', true)
->groupBy('user_id');
$users = DB::table('users')
->joinSub($latestPosts, 'latest_posts', function ($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})->get();
but for WITH
Laravel has no native support for common table expressions.
I've created a package for it: https://github.com/staudenmeir/laravel-cte
You can use it like this:
$query = DB::table('table1')->select('id');
$result = DB::table('table2')
->withExpression('main', $query)
->whereIn('table2.id', DB::table('main')->select('id'))
->get();
Query builder has to be compatible with multiple database engines (mysql, postgresql, sql lite, sql server) and as such only offers support for common functionality.
Assuming your query returns data, you may be able to use the DB:select() method to execute a raw query.
$data = DB::select('WITH main AS (SELECT id FROM table1), SELECT * FROM table2 WHERE table2.id IN (SELECT * FROM main)');
The DB:select method also accepts a second parameter for using named bindings.
Alternatively there are packages available such as laravel-cte that will add the functionality to Eloquent/ Query Builder.

eloquent query with join and sum

I have these tables:
A: id, total_import, other_columns
B: id, a_id, partial_import
I want know all rows in A where the sum of B.partial_import is less then A.total_import.
This is my query:
select A.*, sum(B.partial_import) as sum
from A
inner join B on A.id = B.a_id
group by B.a_id
having sum < A.total or sum is null
Any suggestions on the best solution to replicate it in eloquent will be appreciated.
The fastest way and also a good way is to use query builder.
If you want to use Collection instead, then you should firsly set relationships, and then to build your eloquent query.
I suppose that your A table has many B rows, so the relation could look like (inside A model):
public function B()
{
return $this->hasMany('App\B');
}
Then your eloquent will look like:
App\A::all()
->B()
->groupBy('B.a_id')
->havingRaw('sum < A.total or sum is null');
If you want to use query builder your code will look like this:
Firstly at the beginning of your controller use:
use DB;
And then your query will be something like the following code:
DB::table('A')
->join('B', 'A.id', '=', 'B.a_id')
->groupBy('B.a_id')
->havingRaw('sum < A.total or sum is null')
->selectRaw('A.*, sum(B.partial_import) as sum')
->get();

Complex SQL Query laravel Build

How would I use query builder in Laravel to generate the following SQL statement:
SELECT MAX(QTE) FROM (SELECT SUM(activity_sale_report.quantity_sold)
AS QTE FROM activity_sale_report
GROUP BY activity_sale_report.activity_id) AS T
If you are just using the query builder and not models you can use raw queries
$query = DB::select( DB::raw("SELECT MAX(QTE) FROM (SELECT SUM(activity_sale_report.quantity_sold) AS QTE FROM activity_sale_report GROUP BY activity_sale_report.activity_id) AS T);
I would recommend using the eloquent models, it's easier.

Eloquent query alternative

How can I write the following in Laravel's Eloquent?
SELECT *
FROM
( SELECT real_estate.property_id,
real_estate.amount_offered,
payee.summa
FROM real_estate
LEFT JOIN
(SELECT property_id,
SUM(amount) AS summa
FROM payments
GROUP BY property_id) payee ON payee.property_id = real_estate.property_id ) yoot
WHERE summa = 0.05 * amount_offered
Been on this for a while now and really can't get around it. Lemme explain the whole cause for the panic.
I have two tables, one for property and another for payments made on those properties. Now at any given time I will like to query for what properties have been paid for to a certain percentage hence the 0.05 which reps 5%. As it is the query works but I need an Eloquent alternative for it. Thanks
Anywhere you have subqueries in your SQL you'll need to use DB::raw with Eloquent. In this case you have a big subquery for the FROM statement, so the easiest way would be to do this:
DB::table(
DB::raw('SELECT real_estate.property_id, real_estate.amount_offered, payee.summa FROM real_estate LEFT JOIN (SELECT property_id, SUM(amount) AS summa FROM payments GROUP BY property_id) payee ON payee.property_id = real_estate.property_id)')
)
->where('summa', DB::raw('0.05 * amount_offered'))->get();
Notice I used DB::raw for the WHERE statment value as well. That's because you are doing a multiplication using a column name, and the value would otherwise be quoted as a string.
If you want to go a step further and build each subquery using Eloquent, then convert it to an SQL string and injecting it using DB::raw, you can do this:
$joinQuery = DB::table('payments')
->select('property_id', 'SUM(amount) AS summa')
->groupBy('property_id')
->toSql();
$tableQuery = DB::table('real_estate')
->select('real_estate.property_id', 'real_estate.amount_offered', 'payee.summa')
->leftJoin(DB::raw('(' . $joinQuery . ')'), function ($join)
{
$join->on('payee.property_id', '=', 'real_estate.property_id');
})
->toSql();
DB::table(DB::raw('(' . $tableQuery . ')'))->where('summa', DB::raw('0.05 * amount_offered'))->get();
In this case, the second approach doesn't have any benefits over the first, except perhaps that it's more readable. However, building subqueries using Eloquent, does have it's benefitfs when you'd need to bind any variable values to the query (such as conditions), because the query will be correctly built and escaped by Eloquent and you would not be prone to SQL injection.

how to use union in doctrine query symfony 1.4?

I want to have query like this in mysql:
select a.x, a.y, a.foo, sum(a.bar) as bar_sum from mytable a groupby a.x union select a.x, a.y, a.bar, sum(a.foo) as foo_sum from mytable a groupby a.y
this format is true? and how I can convert it to doctrine query in symfony?
thanks a lot
I believe that UNION is not supported using DQL (doctrine query language). But it looks like someone was able to get around the issue, using a nasty heredoc.
Or, you could just add a custom method in an object peer class and write the query in native sql.
-- Edit --
Use the following as an example (untested):
// Assuming you have the default doctrine setup, where non-object classes are
// appended with Table (your object being Foo)
class FooTable
{
public static function getFooBarUnion()
{
$sql = "select a.x, a.y, a.foo, sum(a.bar) as bar_sum from mytable a groupby a.x union select a.x, a.y, a.bar, sum(a.foo) as foo_sum from mytable a groupby a.y";
$results = Doctrine_Query::create()->query($sql);
return $results;
}
}

Resources