Select where not in with select - php

Im trying to do this SELECT IN SQL SERVER
SELECT cast(datediff(DAY, min([fbh].FBH_DATA_INICIAL), CASE
WHEN max([fbh].FBH_DATA_Final) = '9999-12-31' THEN cast(getdate() AS date)
ELSE max([fbh].FBH_DATA_Final)
END)AS FLOAT) / CAST(365 AS FLOAT) AS duration
FROM [funcionario] AS [f]
INNER JOIN [funcionario_banda_historico] AS [fbh] ON [f].[FUN_ID] = [fbh].[FUN_ID]
AND [f].[FUN_BANDA] = [fbh].[FUN_BANDA]
WHERE NOT EXISTS
(SELECT 1
FROM funcionario_banda_historico t1
WHERE t1.fun_id = [fbh].fun_id
AND t1.FBH_DATA_INICIAL > [fbh].FBH_DATA_Final
AND t1.FUN_BANDA <> [fbh].FUN_BANDA )
AND [f].[FUN_ID] = '9999999'
GROUP BY f.fun_id,
[f].[FUN_BANDA]
Im trying to do this select with where not in and select in LARAVEL
protected function getYearsInBand($userId) {
$fbh = DB::table('funcionario as f')
->join('funcionario_banda_historico as fbh', function($join) {
$join->on('f.FUN_ID', '=', 'fbh.FUN_ID');
$join->on('f.FUN_BANDA', '=', 'fbh.FUN_BANDA');
})
->selectRaw('cast(datediff(day,min([fbh].FBH_DATA_INICIAL),case when max([fbh].FBH_DATA_Final) = "9999-12-31" then cast(getdate() as date) else max([fbh].FBH_DATA_Final) end)AS FLOAT)/CAST(365 AS FLOAT) AS duration')
->where('f.FUN_ID', $userId)
->whereNotIn('1', function($q) {
$q->select('*')
->from('funcionario_banda_historico as t1')
->where('t1.fun_id = [fbh].fun_id')
->where('t1.FBH_DATA_INICIAL > [fbh].FBH_DATA_Final')
->where('t1.FUN_BANDA <> [fbh].FUN_BANDA')
->get();
})
->groupBy('f.FUN_ID', 'f.FUN_BANDA')
->first();
if (!$fbh) {
\Log::debug('funcionario_banda_historico not found'); // Grava no log
return 0;
}
return $fbh->duration;
}
and i had the error Invalid column name 'fun_id = [fbh]'
can you help me?

I think it's not correct syntax for "where" clause in Laravel. Instead you should do:
->whereRaw('t1.FUN_ID = fbh.FUN_ID')
->whereRaw('t1.FBH_DATA_INICIAL > fbh.FBH_DATA_Final')
->whereRaw('t1.FUN_BANDA <> fbh.FUN_BANDA')
OR:
->where('t1.FUN_ID', 'fbh.FUN_ID')
->where('t1.FBH_DATA_INICIAL', '>', 'fbh.FBH_DATA_Final')
->where('t1.FUN_BANDA', '<>', 'fbh.FUN_BANDA')
Notice that I also change "fun_id" to uppercase like everywhere in your code. I don't know if "[fbh]" is correct in Laravel, try to type just "fbh". For raw example you may also need to add Database prefix this way - "DB::getTablePrefix()"

Related

Mysql query to laravel eloquent or query builder nested select

I got the following code that gonna return the sum of score if tgl is '2023-01-01' and then that return value will be selected again to not show any null that the query find
SELECT *
FROM (
SELECT `kodeSales`,
`departemenId`,
`tgl`,
(SELECT SUM(CASE WHEN tgl IN ('2023-01-01') THEN score END)) AS '1'
FROM `history_penjualan`
WHERE `tgl` BETWEEN '2023-01-01' AND '2023-01-30'
`departemenId` = '28'
GROUP BY `tgl`
) AS temp
WHERE '1' IS NOT NULL
How do I do this in laravel eloquent or query builder ?
Try this way,
I tried this and it works. but in here you can change the ->having() statement as havingRaw("'1' IS NOT NULL") or I provided code also works.
$sum_of_score = DB::table('history_penjualan')
->select('kodeSales', 'departemenId', 'tgl', DB::raw("SUM(CASE WHEN tgl = '2023-01-01' THEN score END) AS '1'"))
->whereBetween('tgl', ['2023-01-01', '2023-01-30'])
->where('departemenId', '=', 28)
->groupBy('tgl')
->having('1', '!=', null)
->get();
If you want to learn about Laravel queries refer the document.
https://laravel.com/docs/9.x/queries
or if you need query in dynamic try this way,
$query = DB::table('history_penjualan')
->select(DB::raw('kodeSales, departemenId, tgl, SUM(CASE WHEN tgl = "2023-01-01" THEN score END) as "1"'))
->whereBetween('tgl', ['2023-01-01', '2023-01-30'])
->where('departemenId', '=', '28')
->groupBy('tgl');
$final_data = $query->having('1', '<>', null)->get();
If this is not your expected answer please leave a comment, I'll give another way to do this :)

Convert mysql query into Eloquent laravel query

I am trying to make the following query in laravel:
SELECT a.name AS subname, a.area_id, b.name, u. id, u.lawyer_id,u.active_search,
FROM subarea a
LEFT JOIN user_subarea u ON u.subarea_id = a.id
AND u.user_id = ?
LEFT JOIN branch b ON a.area_id = b.id
The idea is to obtain the subareas and see if the search is activated by the user.
The user_subarea table might have a record that matches the id of the subarea table where the active_search is equal to 0 or 1. If it doesn't exist I would like the query to return null.
While I was able to achieve this in raw SQL when I try the same with eloquent in Laravel I am not returning any value. I have done the following:
$query = DB::table('subarea')
->join('user_subarea', function($join)
{
$value = \Auth::user()->id;
$join->on( 'subarea.id', '=', 'user_subarea.subarea_id')->where('user_subarea.user_id', '=',$value);
})
->leftJoin('branch', 'subarea.area_id', '=', 'branch.id')
->select('branch.name', 'subarea.name as subarea', 'user_subarea.active_search_lawyer', 'user_subarea.id' )
->get();
Any help will be much appreciated.
I found by myself the answer it was just to add a lefjoin in the first join. It is not in the laravel docs but works too.
$query = DB::table('subarea')
->lefjoin('user_subarea', function($join)
{
$value = \Auth::user()->id;
$join->on( 'subarea.id', '=', 'user_subarea.subarea_id')->where('user_subarea.user_id', '=',$value);
})
->leftJoin('branch', 'subarea.area_id', '=', 'branch.id')
->select('branch.name', 'subarea.name as subarea', 'user_subarea.active_search_lawyer', 'user_subarea.id' )
->get();
Try this one, If you get a problem, please comment.
$value = \Auth::user()->id;
$query = DB::table('subarea')
->where('user_subarea.user_id', '=',$value)
->leftJoin('user_subarea', 'subarea.id', '=', 'user_subarea.subarea_id')
->leftJoin('branch', 'subarea.area_id', '=', 'branch.id')
->select('subarea.name AS subname','subarea.area_id', 'branch.name', 'user_subarea.id','user_subarea.lawyer_id','user_subarea.active_search')
->get();

How to write union query in Laravel?

I'm using laravel 5.0 and I have mysql query:
SELECT surat_masuk.id_surat,
surat_masuk.nomor_surat
FROM surat_masuk
WHERE ! EXISTS (SELECT *
FROM file_replace
WHERE id_surat_lama = surat_masuk.id_surat)
AND surat_masuk.id_jenis_surat = '6'
AND surat_masuk.deleted = '0'
UNION
SELECT id_surat_lama
FROM file_replace
WHERE id_surat_baru = '38'
And I write that in my laravel code into:
$nomor_surat1 = DB::table('surat_masuk')->select('id_surat', 'nomor_surat')
->where('id_jenis_surat', '=', $id_jenis_surat)
->where(function ($query) {
$query->where('masa_berlaku_to', '>=', date('Y-m-d'))
->orwhere('masa_berlaku_to', '=', '0000-00-00');
})
->whereExists(function ($query) {
$query
->from('file_replace')
->where('id_surat_lama', '==', 'surat_masuk.id_surat');
})
->where('deleted', '=', '0');
$nomor_surat = DB::table('file_replace')->join('surat_masuk', 'file_replace.id_surat_lama', '=', 'surat_masuk.id_surat')
->select('id_surat_lama', 'nomor_surat')
->where('id_surat_baru', '=', $id_surat_baru)
->union($nomor_surat1)->get();
But I've got nothing showed. Do you know where is the mistakes?
Well, I finally using raw query..
$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = '$someVariable'") );
Please see the answer, that might help you..
SELECT surat_masuk.id_surat,
surat_masuk.nomor_surat
FROM surat_masuk
WHERE ! EXISTS (SELECT *
FROM file_replace
WHERE id_surat_lama = surat_masuk.id_surat)
AND surat_masuk.id_jenis_surat = '6'
AND surat_masuk.deleted = '0'
UNION
SELECT id_surat_lama
FROM file_replace
WHERE id_surat_baru = '38'
//converted to laravel elequent query.
$first_sql=DB::table('surat_masuk as sm1')
->whereNotExists(function($query) {
$query->from('file_replace as fr1')
->where('fr1.id_surat_lama','sm1.id_surat');
})->where('sm1.id_jenis_surat',6)
->where('sm1.deleted',0)
->select('sm1.id_surat', 'sm1.nomor_surat' );
//will return an elequent object, append '->get()' to see the output seperately
$actual_result=DB::table('file_replace as fr2')
->where('fr2.id_surat_baru',38)
->select('fr2.id_surat_lama')
->union($first_sql)
->get();
//will return an array of result set

Laravel subquery

I want to write this query in laravel 5.2
SELECT b.id,
TotalP,
b.booking_amount
FROM booking b
LEFT JOIN
(SELECT sum(amount) AS TotalP,
booking_id
FROM payment
GROUP BY booking_id) AS T ON b.id = T.booking_id
WHERE COALESCE(TotalP, 0) < b.booking_amount
My Question is related to this post.
I wrote a query after searching and studying but It is not working and need more constraint
$result = DB::table('my_booking')
->select('booking_name')
->leftJoin(DB::raw('(SELECT booking_id,sum(amount) as TotalP FROM `my_payment` GROUP BY booking_id) TotalPayment'), function($join)
{
$join->on('my_booking.id', '=', 'TotalPayment.booking_id');
})
->get();
Sql query to get data diffrence of total in 2 tables
You can try this,
$booking_payments = Booking::with('Payment')->find(1);
$total = 0;
foreach($booking_payments->payment as $booking_payment){
$total += $booking_payment->amount;
}
if($booking_payments->booking_amount == $total){
// if the total and booking_amount is equal
}
This should work in Laravel and give you the same exact result as your MySQL query. I moved COALESCE into the subquery select area so that you don't have to write a raw DB where statement in Laravel.
$sql_subquery = "(SELECT COALESCE(SUM(amount),0) AS TotalP,
booking_id
FROM payment
GROUP BY booking_id) AS T";
$result = DB::table('booking AS b')
->leftJoin(DB::raw($sql_subquery), 'b.id', '=', 'T.booking_id')
->where('T.TotalP','<', 'b.booking_amount')
->select('b.id','T.TotalP','b.booking_amount')
->get();

convert SQL query to query builder style

Im trying days to understand how I can convert a SQL query to a query builder style in laravel.
My SQL query is:
$tagid = Db::select("SELECT `id` FROM `wouter_blog_tags` WHERE `slug` = '".$this->param('slug')."'");
$blog = Db::select("SELECT *
FROM `wouter_blog_posts`
WHERE `published` IS NOT NULL
AND `published` = '1'
AND `published_at` IS NOT NULL
AND `published_at` < NOW()
AND (
SELECT count( * )
FROM `wouter_blog_tags`
INNER JOIN `wouter_blog_posts_tags` ON `wouter_blog_tags`.`id` = `wouter_blog_posts_tags`.`tags_id`
WHERE `wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`
AND `id`
IN (
'".$tagid[0]->id."'
)) >=1
ORDER BY `published_at` DESC
LIMIT 10
OFFSET 0");
Where I now end up to convert to the query builder is:
$test = Db::table('wouter_blog_posts')
->where('published', '=', 1)
->where('published', '=', 'IS NOT NULL')
->where('published_at', '=', 'IS NOT NULL')
->where('published_at', '<', 'NOW()')
->select(Db::raw('count(*) wouter_blog_tags'))
->join('wouter_blog_posts_tags', function($join)
{
$join->on('wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
->on('wouter_blog_posts_tags.post_id', '=', 'wouter_blog_posts.id')
->whereIn('id', $tagid[0]->id);
})
->get();
I have read that I can't use whereIn in a join. The error i now get:
Call to undefined method Illuminate\Database\Query\JoinClause::whereIn()
I realy dont know how I can convert my SQL to query builder. I hope when I see a good working conversion of my query I can understand how I have to do it next time.
This work for me:
DB::table('wouter_blog_posts')
->whereNotNull('published')
->where('published', 1)
->whereNotNull('published_at')
->whereRaw('published_at < NOW()')
->whereRaw("(SELECT count(*)
FROM wouter_blog_tags
INNER JOIN wouter_blog_posts_tags ON wouter_blog_tags.id = wouter_blog_posts_tags.tags_id
WHERE wouter_blog_posts_tags.post_id = wouter_blog_posts.id
AND id
IN (
'".$tagid."'
)) >=1")
->orderBy('published_at', 'desc')
->skip(0)
->take(10)
->paginate($this->property('postsPerPage'));
The following Query Builder code will give you the exact SQL query you have within your DB::select:
DB::table('wouter_blog_posts')
->whereNotNull('published')
->where('published', 1)
->whereNotNull('published_at')
->whereRaw('`published_at` < NOW()')
->where(DB::raw('1'), '<=', function ($query) use ($tagid) {
$query->from('wouter_blog_tags')
->select('count(*)')
->join('wouter_blog_posts_tags', 'wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
->whereRaw('`wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`')
->whereIn('id', [$tagid[0]->id]);
})
->orderBy('published_at', 'desc')
->skip(0)
->take(10)
->get();
The subquery condition had to be reversed because you can't have a subquery as the first parameter of the where method and still be able to bind the condition value. So it's 1 <= (subquery) which is equivalent to (subquery) >= 1. The query generated by the above code will look like this:
SELECT *
FROM `wouter_blog_posts`
WHERE `published` IS NOT NULL
AND `published` = 1
AND `published_at` IS NOT NULL
AND `published_at` < Now()
AND 1 <= (SELECT `count(*)`
FROM `wouter_blog_tags`
INNER JOIN `wouter_blog_posts_tags`
ON `wouter_blog_tags`.`id` =
`wouter_blog_posts_tags`.`tags_id`
WHERE `wouter_blog_posts_tags`.`post_id` =
`wouter_blog_posts`.`id`
AND `id` IN ( ? ))
ORDER BY `published_at` DESC
LIMIT 10 offset 0
My process when creating more complex queries is to first create them and try them out in a SQL environment to make sure they work as indended. Then I implement them step by step with the Query Builder, but instead of using get() at the end of the query, I use toSql() which will give me a string representation of the query that will be generated by the Query Builder, allowing me to compare that to my original query to make sure it's the same.

Categories