Laravel - Not getting results from Eloquent query but ->toSql() gets results - laravel-5.4

I have scoured SO regarding this issue but I can't seem to find what's causing my code not to return any result. My issue is that if filter_job_title is queried, I do not get any result eventhough if I use SQL code genereated using ->toSql() and run it in phpmyadmin, I do see the correct result. I need your eyes to see what's wrong with my code:
$resumes = \App\Resume::select(\DB::raw("resumes.*, MATCH (resumes.job_title, resumes.career_summary, resumes.career_awards_and_achievements, resumes.school_or_institution) AGAINST ('{$k}' IN BOOLEAN MODE) AS relevance_1, MATCH (resume_section_experiences.exp_job_title, resume_section_experiences.exp_company, resume_section_experiences.exp_job_description) AGAINST ('{$k}' IN BOOLEAN MODE) AS relevance_2"))
->leftJoin('resume_section_experiences', 'resumes.user_id', '=', 'resume_section_experiences.user_id')
->leftJoin('users', 'users.id', '=', 'resumes.user_id')
->leftJoin('resume_section_languages', 'resume_section_languages.user_id', '=', 'resumes.user_id')
->leftJoin('resume_job_disciplines', 'resume_job_disciplines.user_id', '=', 'resumes.user_id')
->leftJoin('resume_job_functions', 'resume_job_functions.user_id', '=', 'resumes.user_id')
->whereRaw("(MATCH (resumes.job_title, resumes.career_summary, resumes.career_awards_and_achievements, resumes.school_or_institution) AGAINST ('{$k}' IN BOOLEAN MODE) OR MATCH (resume_section_experiences.exp_job_title, resume_section_experiences.exp_company, resume_section_experiences.exp_job_description) AGAINST ('{$k}' IN BOOLEAN MODE)) AND users.active = 1 AND users.privacy_level = 0", ['r1' => $k, 'r2' => $k])
->when(!empty($filter['filter_job_title']), function($query) use ($filter) {
return $query->whereRaw('resume_section_experiences.exp_job_title LIKE "%?%"', $filter['filter_job_title']);
})
->groupBy("resumes.id")
->havingRaw('(relevance_1 + relevance_2) > 0')
->orderByRaw("(relevance_1 + relevance_2) DESC, resumes.job_title ASC")
->simplePaginate(15); //toSql();//simplePaginate(15);
This is the SQL code generated using ->toSql(), formatted for easier view:
select resumes.*,
MATCH (resumes.job_title, resumes.career_summary, resumes.career_awards_and_achievements, resumes.school_or_institution) AGAINST ('engineer' IN BOOLEAN MODE) AS relevance_1,
MATCH (resume_section_experiences.exp_job_title, resume_section_experiences.exp_company, resume_section_experiences.exp_job_description) AGAINST ('engineer' IN BOOLEAN MODE) AS relevance_2
from `resumes`
left join `resume_section_experiences` on `resumes`.`user_id` = `resume_section_experiences`.`user_id`
left join `users` on `users`.`id` = `resumes`.`user_id`
left join `resume_section_languages` on `resume_section_languages`.`user_id` = `resumes`.`user_id`
left join `resume_job_disciplines` on `resume_job_disciplines`.`user_id` = `resumes`.`user_id`
left join `resume_job_functions` on `resume_job_functions`.`user_id` = `resumes`.`user_id`
where (
MATCH (
resumes.job_title, resumes.career_summary, resumes.career_awards_and_achievements, resumes.school_or_institution)
AGAINST ('engineer' IN BOOLEAN MODE
)
OR MATCH (
resume_section_experiences.exp_job_title, resume_section_experiences.exp_company, resume_section_experiences.exp_job_description)
AGAINST ('engineer' IN BOOLEAN MODE)
)
AND users.active = 1
AND users.privacy_level = 0
AND resume_section_experiences.exp_job_title LIKE "%Web Developer%"
group by `resumes`.`id`
having (relevance_1 + relevance_2) > 0
order by (relevance_1 + relevance_2) DESC, resumes.job_title ASC

Related

Sub Query on Query Builder on Laravel

I want to make query builder with this query, but it won't work.
SELECT
karyawan.id,
karyawan.nama_lengkap,
departemen.nama,
jabatan.nama,
(
SELECT
tingkat
FROM
riwayat_pendidikan
WHERE
karyawan_id = karyawan.id
ORDER BY
tahun_selesai DESC
LIMIT
1
) AS pendidikan_terakhir
FROM
karyawan
INNER JOIN jabatan ON karyawan.jabatan_id = jabatan.id
INNER JOIN departemen ON jabatan.departemen_id = departemen.id;
Well its done using this Query Builder , Thanks guys i'm using this https://sql-to-laravel-builder.herokuapp.com/
DB::table('karyawan')
->select('karyawan.id as id','karyawan.nama_lengkap as nama','departemen.nama as departemen'
,'jabatan.nama as jabatan','karyawan.jenis_kelamin','karyawan.nomor_hp_whatsapp','karyawan.status_pegawai',
'karyawan.tanggal_mulai_bekerja','karyawan.tanggal_keluar_bekerja','karyawan.tanggal_akhir_kontrak',
'karyawan.telepon_rumah','karyawan.telepon_kantor',
DB::raw('(SELECT CONCAT(riwayat_pendidikan.tingkat," ", riwayat_pendidikan.jurusan)
AS FIRSTNAME FROM riwayat_pendidikan WHERE karyawan_id = karyawan.id ORDER BY
tahun_selesai DESC LIMIT 1 ) AS pendidikan_terakhir'))
->join('jabatan','karyawan.jabatan_id','=','jabatan.id')
->join('departemen','jabatan.departemen_id','=','departemen.id')
->where('departemen.nama','=','Staff')
->get();
use Illuminate\Support\Facades\DB;
DB::table('karyawan')
->join('jabatan', 'jabatan.id', '=', 'karyawan.jabatan_id')
->join('departemen', 'departemen.id', '=', 'jabatan.departemen_id')
->select([
'karyawan.id',
'karyawan.nama_lengkap',
'departemen.nama',
'jabatan.nama',
])
->addSelect([
'pendidikan_terakhir' => DB::table('riwayat_pendidikan')
->select('tingkat')
->whereColumn('riwayat_pendidikan.karyawan_id', 'karyawan.id')
->orderByDesc('tahun_selesai')
->limit(1)
])->get();
Documentation

Laravel Query Builder Sub Query not returning specific inside loop

I am trying to aggregate the following totals into a new collection to use a report, the Sub Query for total_outbound is not returning the correct count for the specific campaign_job_id
$campaign_jobs_summary = new Collection();
foreach ($campaign_jobs as $campaign_job) {
$campaign_job_totals = DB::table("campaign_jobs")
->select('campaign_jobs.deploy_date', 'campaign_jobs.campaign_id', 'campaign_jobs.id as campaign_job_id', 'campaign_jobs.start_time as local_start_time',
'campaign_jobs.start_time as local_start_time', 'campaign_jobs.start_time as local_start_time', 'campaign_jobs.start_time as local_start_time',
DB::raw("(select companies.name from companies join brands on brands.company_id = companies.id where brands.id =$campaign->brand_id) as company"),
DB::raw("(select count(id) from campaign_results where direction = 'outbound-api' and reCall = '0' and campaign_job_id =$campaign_job->id ) as total_outbound"),
DB::raw("(select count(id) as aggregate from campaign_results where com_platform_status = 'completed' and direction = 'outbound-api' and campaign_job_id = $campaign_job->id ) as total_answered")
)
->whereCampaignId(35)
->get();
$campaign_jobs_summary = $campaign_jobs_summary->push($campaign_job_totals);
}
return $campaign_jobs_summary;
Change the line of code to
DB::raw("(select count(id) from campaign_results where direction = 'outbound-api' and reCall = '0' and campaign_job_id =".$campaign_job->id." ) as total_outbound");
ok the issue was returning the query as get() and not first() inside the loop and changing whereCampaignId to whereId by campaign_jobs.id

Laravel 5.2 - Odd Results When using Left Join on Subquery

I have the following query:
$products = Product::leftJoin(DB::Raw('(SELECT imageable_id, MIN(created_at) as min_created_at
FROM images WHERE imageable_type = "App\\\Product"
GROUP BY imageable_id) AS subquery'), function($join) {
$join->on('subquery.imageable_id', '=', 'products.id');
})
->leftJoin('images', function ($join) {
$join->on('images.imageable_id', '=', 'subquery.imageable_id')
->where('images.created_at', '=', 'subquery.min_created_at');})
->select('products.*', 'images.file_path')
->paginate(5);
When I die and dump the query log, the above gets translated as follows:
"query" => """
select `products`.*, `images`.`file_path` from `products`
left join (SELECT imageable_id, MIN(created_at) as min_created_at
FROM images WHERE imageable_type = "App\\Product"
GROUP BY imageable_id) AS subquery on `subquery`.`imageable_id` = `products`.`id`
left join `images` on `images`.`imageable_id` = `subquery`.`imageable_id` and `images`.`created_at` = ?
limit 5 offset 0
"""
"bindings" => array:1 [
0 => "subquery.min_created_at"
]
Which looks correct, though I'm unsure why a binding has been added for subquery.min_created_at
Now when I execute the above the query in laravel images.file_path is always null when clearly I know there are related images. When I test the above query by pasting it and running directly in MySQL command line I get the expected results i.e. for products which have images, file_path for image is not null. The only difference when I run in MySQL command line is that I'm not doing any binding for subquery.min_created_at - I simply replaced the ? with subquery.min_created_at
Any ideas why the query is behaving this way. If I remove the second left join it works correctly but then I can't select the first created image to load e.g doing the following give me the file_path:
$products = Product::leftJoin(DB::Raw('(SELECT imageable_id, file_path
FROM images WHERE imageable_type = "App\\\Product"
GROUP BY imageable_id) AS subquery'), function($join) {
$join->on('subquery.imageable_id', '=', 'products.id');
})
->select('products.*', 'subquery.file_path')
->paginate(5);
Ideally I want to get my original query working in - any help appreciated.
You are using ->where() for your second join condition:
->where('images.created_at', '=', 'subquery.min_created_at')
This generates
and `images`.`created_at` = ?
which the binding is for.
Instead you should use ->on();
$join->on('images.imageable_id', '=', 'subquery.imageable_id')
->on('images.created_at', '=', 'subquery.min_created_at');

SQL Query with JOIN, WHERE and AND clause to convert in Laravel queries

I'm having problem converting my SQL query to laravel queries. I want to join two tables users and messages so that i can get the users that has conversation with other users.
Database Structure:
Users:
Messages:
This is my SQL query where I get what I want:
SELECT u.id, c.id, u.first_name, u.last_name FROM messages c, users u
WHERE (CASE WHEN c.user_one = #USERID THEN c.user_two = u.ID WHEN c.user_two = #USERID THEN c.user_one= u.id END )
AND ( c.user_one = #USERID OR c.user_two = #USERID ) Order by c.id DESC Limit 20
This is my Laravel query:
DB::table('messages')
->join('users', function($join) use ($user_id) {
$join->select(DB::raw('CASE WHEN messages.user_one = ' . $user_id . ' THEN messages.user_two = ' . $user_id . 'WHEN messages.user_two = ' . $user_id . ' THEN messages.user_one = ' . $user_id));
$join->on(function($query) use ($user_id)
{
$query->where('messages.user_one', '=', $user_id);
$query->orWhere('messages.user_two', '=',$user_id);
});
})
->select('users.*', 'messages.*')
->get();
UPDATE:
Sorry my original answer was not injecting variables in a secure way. Please use this for securely injecting variables in raw queries.
SQL injection security in raw statements.
In raw queries we need remember to pass all variables to our mysql
database using provided second argument.
In your case, you just place question marks placeholders, where you want to have your variables injected and then put your variables in same order as your placeholders in your second argument array.
Source: http://s4.jeffsbio.co.uk/laravel-5-query-builder-where-raw-2
Updated Query:-
DB::table('messages as m')
->join('users as u',function($join){
$join->on('u.id','=','m.user_one')
->orOn('u.id','=','m.user_two');
})
->where(function($query) use($user_id){
$query->where('m.user_one','=',$user_id);
$query->orWhere('m.user_two','=',$user_id);
})
->where(function($query) use($user_id){
$query->whereRaw(
'CASE WHEN m.user_one = ?'.
' THEN m.user_two = u.id'.
' WHEN m.user_two = ?'.
' THEN m.user_one = u.id END',[$user_id,$user_id]);
//here we passed the variables in exact order of their usage in query
})
->select('u.id as user_id', 'm.id as messages_id','u.first_name','u.last_name')
->orderBy('m.id','DESC')
->limit('20')
->get(
Original Answer:
You can't use select clause in join clause like you have.
Use this :-
DB::table('messages as m')
->join('users as u',function($join){
$join->on('u.id','=','m.user_one')
->orOn('u.id','=','m.user_two');
})
->where(function($query) use($user_id){
$query->where('m.user_one','=',$user_id);
$query->orWhere('m.user_two','=',$user_id);
})
->where(function($query) use($user_id){
$query->whereRaw(DB::raw(
'CASE WHEN m.user_one = '.$user_id.
' THEN m.user_two = u.id'.
' WHEN m.user_two = '.$user_id.
' THEN m.user_one = u.id END'));
})
->select('u.id as user_id', 'm.id as messages_id','u.first_name','u.last_name')
->orderBy('m.id','DESC')
->limit('20')
->get();

Rails3 NOT IN query takes string as a value

I am trying to select users who don't have post in the forum list. For that I wrote a query like this
users_id = Post.where(:forum_id => 1).collect { |c| c.user_id }
#users = User.where('topic_id = ? and id not in ? ', "#{#topic.id}", "#{users_id}")
This code throws mysql error, and in my log
SELECT `user`.* FROM `user` WHERE (forum_id = '2222' and id not in '[5877, 5899, 5828, 5876, 5841, 5838, 5840, 5882, 5881, 5870, 5842, 5843, 5844, 5845, 5889, 5896, 5869, 5847, 5849, 5850, 5855, 5857, 5859, 5867, 5861, 5863, 5865, 5868, 5829, 5830, 5831, 5832, 5833, 5900, 6326, 6326, 6332, 5898, 6333, 6334, 6335, 6336, 6339, 7034, 7019, 6336, 5887, 5827, 9940, 9943, 9949, 7030, 9979, 9980, 5892, 9896, 14208, 14224, 14281, 14282, 14283, 5894, 5895, 14689, 14717]'
In mysql I execute the following query, and got the expected result
select * from users where topic_id = 1 and id not in (select users_id from posts where forum_id = 1);
The above query in rails doesn't seem to work..
Try this:
users_ids = Post.where(:forum_id => 1).collect { |c| c.user_id }
#users = User.where('topic_id = ? and id not in (?) ', #topic.id, users_ids)
Also, I advice you to make some changes:
Use pluck instead of collect (pluck is on the DB level)(pluck doc ; pluck vs. collect)
users_ids = Post.where(:forum_id => 1).pluck(:user_id)
name the table in the where clause to avoid ambiguous calls (in where chaining for example):
User.where('users.topic_id = ? AND users.id NOT IN (?)', #topic.id, users_ids)
The final code:
users_ids = Post.where(:forum_id => 1).pluck(:user_id)
#users = User.where('users.topic_id = ? AND users.id NOT IN (?)', #topic.id, users_ids)