Eloquent query with COALESCE, IF, complex ON clause - php

i'd like to ask, how would you write the following query in Laravel Eloquent?
Please note the COALESCE, IF, and the complex LEFT JOIN ... ON (... AND ...).
SELECT COALESCE(IF(customer_group_id=6, prices.price, NULL), products.price) AS finalPrice, prices.customer_group_id, products.*, product_translations.*
FROM `product_categories`
LEFT JOIN `products` ON `product_categories`.`product_id` = `products`.`id`
LEFT JOIN `product_translations` ON `product_translations`.`product_id` = `products`.`id`
LEFT JOIN `prices`
ON (`products`.`id` = `prices`.`product_id` AND `prices`.`customer_group_id` = 6 )
WHERE `product_translations`.`locale` = 'it'
AND `products`.`online` = 1
AND `products`.`sellable` = 1
AND `category_id` = 22
UPDATE: By far, what i came up with is the following:
ProductCategory::leftjoin('products', 'product_categories.product_id', '=', 'products.id')
->leftJoin('product_translations', 'product_translations.product_id', 'products.id')
->leftJoin('prices', function($join) use($customer_group_id) {
$join->on('products.id', '=', 'prices.product_id')
->on('prices.customer_group_id', '=', DB::raw($customer_group_id));
})
->select(
DB::raw('coalesce(if(customer_group_id='.$customer_group_id.',prices.price,NULL), products.price) AS finalPrice'),
'prices.customer_group_id',
'products.*',
'product_translations.*'
)
->where('product_translations.locale', '=', $locale)
->where('products.online', '=', true)
->where('products.sellable', '=', true)
->where('category_id', '=', $this->id);

Related

how to turn Aggregates with multiple table into USE DB at laravel?

How can I write the query like that on Laravel, btw I'm using DB
I followed this instruction
https://dba.stackexchange.com/questions/175786/join-multiple-tables-for-aggregates, but still not get it
mysql query:
SELECT inptkegiatan.IDKEGIATAN,
(SELECT COUNT(kuesioner.PERTANYAAN)
FROM kuesioner
WHERE inptkegiatan.IDKEGIATAN = kuesioner.IDKEGIATAN) as totalPertanyaan,
(SELECT SUM(hasilkuesioner.JAWABAN)
FROM hasilkuesioner
WHERE kuesioner.IDKEGIATAN = hasilkuesioner.IDKEGIATAN) as totalJawaban,
(SELECT COUNT(regiskegiatan.IDKEGIATAN)
FROM regiskegiatan
WHERE hasilkuesioner.IDKEGIATAN = regiskegiatan.IDKEGIATAN ) as totalUser
FROM inptkegiatan
LEFT JOIN kuesioner ON inptkegiatan.IDKEGIATAN = kuesioner.IDKEGIATAN
LEFT JOIN hasilkuesioner ON inptkegiatan.IDKEGIATAN = hasilkuesioner.IDKEGIATAN
LEFT JOIN regiskegiatan ON inptkegiatan.IDKEGIATAN = regiskegiatan.IDKEGIATAN
GROUP BY inptkegiatan.IDKEGIATAN
I tried this on my Laravel with that url, still not get it
$datatwo = DB::table('inptkegiatan')
->join('kuesioner', 'inptkegiatan.IDKEGIATAN', '=', 'kuesioner.IDKEGIATAN')
->join('hasilkuesioner', 'inptkegiatan.IDKEGIATAN', '=', 'hasilkuesioner.IDKEGIATAN')
->join('regiskegiatan', 'inptkegiatan.IDKEGIATAN', '=', 'regiskegiatan.IDKEGIATAN')
->where('IDNARASUMBER', '=', $value->PROFILEUSERS_ID)
->select('kuesioner.PERTANYAAN', 'hasilkuesioner.*', 'regiskegiatan.*',
DB::raw('count(DISTINCT(kuesioner.IDKEGIATAN)) + SUM(DISTINCT(hasilkuesioner.IDKEGIATAN)) as articles')
)
->groupBy('inptkegiatan.IDKEGIATAN')
->get();
First of all, use leftJoin instead of join, because join is alternate for innerJoin
$datatwo = DB::table('inptkegiatan')
->leftJoin('kuesioner', 'inptkegiatan.IDKEGIATAN', '=', 'kuesioner.IDKEGIATAN')
->leftJoin('hasilkuesioner', 'inptkegiatan.IDKEGIATAN', '=', 'hasilkuesioner.IDKEGIATAN')
->leftJoin('regiskegiatan', 'inptkegiatan.IDKEGIATAN', '=', 'regiskegiatan.IDKEGIATAN')
->where('inptkegiatan.IDNARASUMBER', '=', $value->PROFILEUSERS_ID)
->select([
'inptkegiatan.IDKEGIATAN',
\DB::raw('SELECT COUNT(kuesioner.PERTANYAAN)
FROM kuesioner
WHERE inptkegiatan.IDKEGIATAN = kuesioner.IDKEGIATAN) as totalPertanyaan'),
\DB::raw('(SELECT SUM(hasilkuesioner.JAWABAN)
FROM hasilkuesioner
WHERE kuesioner.IDKEGIATAN = hasilkuesioner.IDKEGIATAN) as totalJawaban'),
\DB::raw('(SELECT COUNT(regiskegiatan.IDKEGIATAN)
FROM regiskegiatan
WHERE hasilkuesioner.IDKEGIATAN = regiskegiatan.IDKEGIATAN ) as totalUser')
])
->groupBy('inptkegiatan.IDKEGIATAN')
->get();
Try with this. It should work

How to write a subquery in Laravel query builder

i have an mssql query that looks like this:
SELECT * FROM (
SELECT a.Client, ad.Kto, a.Address, a.Matchcode, a.Name1, a.country, a.ZIP, a.Street FROM [HeadQuarter].[dbo].[Addresses] a
INNER JOIN [HeadQuarter].[dbo].[AddressesDetails] ad ON (a.Client = ad.Client AND
a.Address = ad.Address)
WHERE ad.Active <> 0 AND
(a.USER_emailactive = 0 OR a.USER_emailactive IS NULL)
) client_id
WHERE (a.Country = 'AT' AND a.ZIP BETWEEN '0000' AND '5000')
i converted the inner select into Laravel query builder
\DB::connection('sqlsrv')
->table('[HeadQuarter].[dbo].[Addresses]')
->join([HeadQuarter].[dbo].[AddressesDetails], function($join){
$join->on('[HeadQuarter].[dbo].[Addresses].Client', '=', '[HeadQuarter].[dbo].[AddressesDetails].Client')
->on('[HeadQuarter].[dbo].[Addresses].Address', '=', '[HeadQuarter].[dbo].[AddressesDetails].Address')
})
->select('[HeadQuarter].[dbo].[Addresses].Client, [HeadQuarter].[dbo].[AddressesDetails].Kto,....')
->where('[HeadQuarter].[dbo].[AddressesDetails].Active', '<>', '0')
->whereRaw('(a.USER_emailactive = 0 OR a.USER_emailactive IS NULL)')
->get();
and this is working. But now how can i get the
SELECT * FROM (..inner query..) client_id
WHERE (a.Country = 'AT' AND a.ZIP BETWEEN '0000' AND '5000')
convert to my query builder. sure i could use ->select() and write the raw sql query but i need this in the query builder because my inner and outer where clause i optional
I guess you could simplify your query as below, there is not need for sub query
SELECT a.Client, ad.Kto, a.Address, a.Matchcode, a.Name1, a.country, a.ZIP, a.Street
FROM [HeadQuarter].[dbo].[Addresses] a
INNER JOIN [HeadQuarter].[dbo].[AddressesDetails] ad
ON (a.Client = ad.Client AND a.Address = ad.Address)
WHERE ad.Active <> 0
AND a.Country = 'AT'
AND a.ZIP BETWEEN '0000' AND '5000'
AND (a.USER_emailactive = 0 OR a.USER_emailactive IS NULL)
In query builder you can use Parameter Grouping
\DB::connection('sqlsrv')
->table('[HeadQuarter].[dbo].[Addresses] as a')
->join('[HeadQuarter].[dbo].[AddressesDetails] as b', function($join){
$join->on('a.Client', '=', 'ad.Client')
->on('a.Address', '=', 'ad.Address');
})
->select('a.Client', 'ad.Kto', 'a.Address', 'a.Matchcode', 'a.Name1', 'a.country', 'a.ZIP', 'a.Street')
->where('ad.Active', '<>', '0')
->where(function ($query) {
$query->whereNull('a.USER_emailactive')
->orWhere('a.USER_emailactive', '=', '0');
})
->where(function ($query) {
$query->orWhere(function ($query) {
$query->where('a.Country', '<>', 'AT')
->whereBetween('a.ZIP', ['0000', '5000']);
})->orWhere(function ($query) {
$query->where('a.Country', '<>', 'Foo')
->whereBetween('a.ZIP', ['0000', '5000']);
})->orWhere(function ($query) {
$query->where('a.Country', '<>', 'Bar')
->whereBetween('a.ZIP', ['0000', '5000']);
});
})
->get();

How to effectively using laravel 5.5 eloquent on complex join and group

I have this query that successfully run on mysql workbench:
SELECT
any_value(u.username),
any_value(b.name),
any_value(gc.visit_cycle_id),
any_value(gc.group_number),
any_value(dc.total_customer),
count(*) as total_day
FROM
trackgobackenddb.group_cycles gc
LEFT JOIN (
SELECT
any_value(dc.group_cycle_id) as group_cycle_id,
count(*) as total_customer
FROM
trackgobackenddb.destination_cycles dc
GROUP BY dc.group_cycle_id
) dc ON dc.group_cycle_id = gc.id
LEFT JOIN visit_cycles vc ON gc.visit_cycle_id = vc.id
LEFT JOIN users u ON vc.user_id = u.id
LEFT JOIN branches b ON vc.branch_id = b.id
GROUP BY gc.visit_cycle_id, gc.group_number;
How to convert that query so I can use laravel eloquent or query builder?
You can use DB::select to run complex raw SQL
$sql = "";
$data = DB::select($sql);
Here's my untested attempt using the query builder:
DB::table('group_cycles AS gc')
->leftJoin('destination_cycles AS dc', function ($join) {
$join->on('dc.group_cycle_id', '=', 'gc.id')
->select(['dc.group_cycle_id AS group_cycle_id', DB::raw('select count(*) AS total_customer')]);
})
->leftJoin('visit_cycles AS vc', function ($join) {
$join->on('gc.visit_cycle_id', '=', 'vc.id');
})
->leftJoin('users AS u', function ($join) {
$join->on('vc.user_id', '=', 'u.id');
})
->leftJoin('branches AS b', function ($join) {
$join->on('vc.branch_id', '=', 'b.id');
})
->groupBy('gc.visit_cycle_id', 'gc.group_number')
->get();

Query from two tables laravel with multiple conditions

I'm trying to write this query in Laravel query
SELECT
table1.*, table2.*
FROM
table1
LEFT JOIN
table2
ON
(table1.id = table2.id AND (table2.field = '' OR table2.field >= '0'))
WHERE
table.id = id
I have problem with how to add inner part AND ( ... ) to the query? Here is what I have so far
$query = Table::select(
DB::Raw('table1.*, table2.*'))
->leftJoin('table2', function($join) {
$join->on('table1.id', '=', 'table2.id')
->where('table2.field', '=', '')
->orwhere('table2.field', '=', '50');
})->where('table1.id', BaseController::getCurrentUser()->id)
->get();
I miss where and how to add AND ...
Do you need to have the AND part as part of ON? If you move it to the WHERE part of your query you could use something like:
$query = Table::select('table1.*', 'table2.*')
->leftJoin('table2', 'table1.id', '=', 'table2.id')
->where('table1.id', BaseController::getCurrentUser()->id)
->where(function ($query){
$query->where('table2.field', '')
->orWhere('table2.field', 50)
});
The result should be the same as from your original query.

Passing parameter bindings to Laravel query builder?

I currently have a SQL query which a fantastic stackoverflow member helped me with earlier today. At the moment it works absolutely fine and the way I want it to work.
The only problem is it's RAW SQL and I'd very much like to get this working with the Laravel Query Builder.
SORRY THIS IS AN EDIT - HERE IS THE ORIGINAL QUERY:
$addresses = DB::select(
DB::raw('
(SELECT
"Company" AS object_type_name,
companies.company_name AS object_name,
addresses.*
FROM
addresses
INNER JOIN
companies
ON
addresses.object_id = companies.id
WHERE
addresses.object_type = 2)
UNION ALL
(SELECT
"Job" AS object_type_name,
jobs.job_title AS object_name,
addresses.*
FROM
addresses
INNER JOIN
jobs
ON
addresses.object_id = jobs.id
WHERE
addresses.object_type = 4)
'));
Here is the code I have so far:
$bindings = array(
'soft_deleted' => 0,
'user' => 1,
'company' => 2,
'candidate' => 3,
'job' => 4,
);
$companies = DB::table('addresses')->select(
'addresses.*',
'companies.company_name as object_name'
)->where('addresses.soft_deleted', '=', 0)->join('companies', function($join) use ($bindings){
$join->on('addresses.object_id', '=', 'companies.id')
->where('addresses.object_type', '=', $bindings['company']);
});
$jobs = DB::table('addresses')->select(
'addresses.*',
'jobs.job_title as object_name'
)->join('jobs', function($join) use ($bindings){
$join->on('addresses.object_id', '=', 'jobs.id')
->where('addresses.object_type', '=', $bindings['job']);
});
$addresses = $companies->unionAll($jobs)->get();
With the code above I'm getting the following error:
SQLSTATE[HY093]: Invalid parameter number (SQL: (select addresses., companies.company_name as object_name from addresses inner join companies on addresses.object_id = companies.id and addresses.object_type = 2 where addresses.soft_deleted = 0) union all (select addresses., jobs.job_title as object_name from addresses inner join jobs on addresses.object_id = jobs.id and addresses.object_type = ?))
I've done hours worth of searching but I can't seem to find the answer to this little problem.
I managed to fix it. It was as simple as removing the ->where from within each join closure and chaining it to the join itself and not nesting it.
Before:
$companies = DB::table('addresses')->select(
'addresses.*',
'companies.company_name as object_name'
)->where('addresses.soft_deleted', '=', 0)->join('companies', function($join) use ($bindings){
$join->on('addresses.object_id', '=', 'companies.id')
->where('addresses.object_type', '=', $bindings['company']);
});
$jobs = DB::table('addresses')->select(
'addresses.*',
'jobs.job_title as object_name'
)->join('jobs', function($join) use ($bindings){
$join->on('addresses.object_id', '=', 'jobs.id')
->where('addresses.object_type', '=', $bindings['job']);
});
After:
$companies = DB::table('addresses')->select(
'addresses.*',
'companies.company_name as object_name'
)->where('addresses.soft_deleted', '=', 0)->join('companies', function($join){
$join->on('addresses.object_id', '=', 'companies.id');
})->where('addresses.object_type', '=', 2);
$jobs = DB::table('addresses')->select(
'addresses.*',
'jobs.job_title as object_name'
)->where('addresses.soft_deleted', '=', 0)->join('jobs', function($join){
$join->on('addresses.object_id', '=', 'jobs.id');
})->where('addresses.object_type', '=', 4);
$addresses = $companies->unionAll($jobs)->get();
Hope this helps someone.

Categories