Laravel selectSub with IFNULL - mysql

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);

Related

How to write the below eloquent query code using raw query in laravel?

My eloquent query:
$data = (new Model())->whereDate('start_date', '<=', Carbon::today())
->whereDate('end_date', '>=', Carbon::today())
->count();
The raw query I have tried:
$data = (new Model())->select(DB::raw("COUNT(id) as countData where date(start_date) <= NOW() and date(end_date) >= NOW()"))->get();
How can I write my eloquent query as raw query. The below raw query gives me syntax violation error;
This is because of how you are constructing your query. If you inspect the generated SQL statement you'll see that the SQL FROM clause is actually on the end of your statement and not at all where it should be.
You'll want to split your WHERE clauses out and use either where or whereRaw. For example:
$data = (new Model)->select(DB::raw('COUNT(id) as countData'))
->whereRaw('date("start_date") <= NOW() AND date("end_date") >= NOW()')
->get();
Your question was a little unclear but if you want to do what you did with eloquent in raw query, be noted that the select function of DB in raw by itself, so simply write your query inside select function:
$tableName = (new Model)->getTable();
$data = DB::select("
SELECT COUNT(`id`) as `countData` FROM `$tableName`
WHERE DATE(`start_date`) <= NOW() AND DATE(`end_date`) >= NOW()
")->first();
Alternatively you may use whereRaw function of your Model:
$data = Model::whereRaw(
"DATE(`start_date`) <= NOW() AND DATE(end_date) >= NOW()"
)->count();

raw SQL to laravel query builder

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')

Laravel select is not working with subquery

I was trying to write laravel function to execute query given below. But i am not getting any result. Please help..
Here is my query
SELECT leads_followup_status_list.followup_status_name, COUNT(FUP.followup_status) FROM leads_enquiry_details LEFT JOIN (SELECT max(followup_id) as FID,leads_enquiry_details_enquiry_id as LID,leads_followup_details.followup_comment,followup_date,followup_status from leads_followup_details WHERE leads_followup_details.followup_deleted=1 GROUP by LID )fup on leads_enquiry_details.enquiry_id=fup.LID JOIN leads_followup_status_list on leads_followup_status_list.followup_status_id =FUP.followup_status where leads_enquiry_details.enquiry_deleted=1 and leads_enquiry_details.enquiry_status=1 GROUP by FUP.followup_status
This is my function
public function getFollowupStatusCount($parametr=null){
$status_counts = LeadsDetails::where('enquiry_deleted', '=', 1)
->where('enquiry_status', 1)
->leftjoin(DB::raw('(SELECT max(followup_id) as FID,leads_enquiry_details_enquiry_id as LID,
leads_followup_details.followup_comment,
followup_date,followup_status from leads_followup_details GROUP by LID )
FUP'),
function($leftjoin)
{
$leftjoin->on('leads_enquiry_details.enquiry_id', '=', 'fup.LID');
})
->leftjoin('leads_followup_status_list.followup_status_id','leads_followup_status_list','fup.followup_status')
->select('COUNT(FUP.followup_status) as count', 'leads_followup_status_list.followup_status_name as status',
'leads_followup_status_list.followup_status_color_code as color')
->groupBy('followup_status');
return $status_counts;
}
Ok so I've noticed 2 problems. First, you miss ->get() at the end of you request. Second, your parameters order is wrong on second leftJoin. Should be:
->leftJoin('leads_followup_status_list',
'leads_followup_status_list.followup_status_id', '=', 'fup.followup_status')
Should work after these fixes.
Thank you very much #Pavel Lint, There were one mistake too . I should have used select( DB::raw('count(FUP.followup_status) as count'),' instead of count..

How to convert RIGHT LEFT functions to codeigniter active record

I have a query like this:
SELECT RIGHT(id, 1) id_root
FROM user
WHERE LENGTH(id) = 3
and LEFT(id, 1) = '0'
And how to convert that's query to active record in codeigniter.
My problem is with syntax RIGHT( id, 1 ) and also at LEFT(id,1)='0'
$result_arr = $this->db
->select("RIGHT(id, 1) id_root", FALSE)
->from("user")
->where(
array("LENGTH(id)"=> 3, "LEFT(id, 1) =" => 0)
)->get()
->result_array();
Or you can simply use $this->db->query("You SQL");
$query = "SELECT RIGHT(id, 1) id_root
FROM user
WHERE LENGTH(id) = ?
and LEFT(id, 1) = ? ";
$result_arr = $this->db->query($query, array(3, 0))->result_array();
You can produce your query like this
$this->db->from('user');
$this->db->select('RIGHT(id, 1) id_root',false);
$this->db->where('LENGTH(id)',3,true);
$this->db->where('LEFT(id, 1) =','0',true);
$results=$this->db->get()->result();
Remember if you want to use mysql function at your select query which may break mysql syntax by codeigniter use false as 2nd parameter so that codeigniter does not protect/covert your fields.
Same for where, if you want to use mysql function or other function which may break mysql syntax by CI use 3rd parameter as true so that codeigniter does not convert your fields.
See details at documentation
Simplest way to get any query result using $this->db->query('YOUR_QUERY') But I prefer using CI Active record's functions.
$query = "SELECT RIGHT(id, 1) id_root
FROM user
WHERE LENGTH(id) = 3
and LEFT(id, 1) = '0'";
$result = $this->db->query($query);

Converting MYSQL to Codeigniter

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.