How to use MAX function in yii2 query? - mysql

I have a query:
SELECT hs.*
FROM hire_screening hs
INNER JOIN
(SELECT resume_id, MAX(created_date) AS MaxDateTime
FROM hire_screening
GROUP BY resume_id) hire_screening
ON hs.resume_id = hire_screening.resume_id
AND hs.created_date = hire_screening.MaxDateTime
This is my table:
I need the answer like this:
I tried this:
$query = HireScreening::find()-
->select(["hire_screening.screening_id","hs.resume_id",
"MAX(hs.created_date) AS
MaxDateTime","hs.screening_by","hsl.screening_level as
hr_level","hss.screening_status as
hr_status","hr.candidate_name","hsm.screening_mode as
hr_mode","hire_screening.created_date","hs.screening_date"])
->innerJoin('hire_screening as hs','hs.resume_id =
hire_screening.resume_id')
->leftJoin('hire_screening_level as
hsl','hire_screening.screening_level = hsl.id')
->leftJoin('hire_screening_mode as
hsm','hire_screening.screening_mode = hsm.id')
->leftJoin('hire_screening_status as
hss','hire_screening.screening_status = hss.id')
->leftJoin('hire_resume as
hr','hire_screening.resume_id=hr.resume_id')
//->where(['hire_screening.created_date = MaxDateTime'])
->groupBy(['resume_id']);
//->having(['hire_screening.created_date' =>
'hs.MaxDateTime']);
$query->orderBy(['created_date' => SORT_DESC]);
But it didn't shows the answer. I need the distinct resume_id's with latest created date. The sql query shows the correct answer.I want to write this query in my search model. Please help me to convert this query into yii2.

If there is a table MyTable, then you can use simplier query grouping the table by resume_id:
SELECT
screening_id,
resume_id,
screening_by,
screening_date,
screening_level,
screening_mode,
screening_status,
reject_reason,
remarks,
created_by,
MAX(created_date) AS created_date
FROM MyTable
GROUP BY resume_id;
Using simplify query helps to avoid an errors. Also you could create a view or a stored procedure using the query and call this from your PHP code.

Related

How to use pagination on DB::select(query) - Laravel

i have some query and i just know how to query on mysql (phpmyadmin)
i got information if using DB::select we cannot to use paginate, so we need change to DB::table(some query) to using pagination.
but the problem is i am confuse how to convert my query into DB::table(some query)
Here is my code
$daily = DB::select("
SELECT
employees.employee_name,
COUNT(DISTINCT DATE(attendance.attendance_datetime)) as jumlah,
locations.location_name,
TIME(MIN(attendance.attendance_datetime)) as check_in,
CASE
WHEN ISNULL(TIME(MIN(attendance.attendance_datetime))) THEN attendance_absence.remarks
WHEN TIME(MIN(attendance.attendance_datetime)) > '08:05:00' THEN (SELECT TIMEDIFF('08:05:00', MIN(TIME(attendance_datetime))))
WHEN TIME(MIN(attendance.attendance_datetime)) <= '08:05:00' THEN 'Good'
ELSE 'No Record'
END as detail_telat,
attendance_absence.remarks as remarks
FROM
employees
LEFT JOIN attendance ON employees.employee_name = attendance.attendance_name AND DATE(attendance.attendance_datetime) = '$date'
LEFT JOIN locations ON employees.location_id = locations.id
LEFT JOIN attendance_absence ON attendance_absence.employee_name = employees.employee_name AND attendance_absence.absences_date = '$date'
WHERE locations.location_name LIKE '%'
GROUP BY employees.employee_name
ORDER BY employees.employee_name
")->paginate(3);
please help me to convert my query into eloquent or query builder, or any suggestion ?
Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually.
Check documentation

Using union in codeigniter query builder, and filter in a virtual mysql column

In my project I am using datatables plugin with serverside processing. It works fine untill i do a search or order(sort) operation because it needs active record to do that.
My scenario is, i have an account table, revenue table and payment table, and I want to view all the data of revenue and payment table, thats why I need a union. my query is like below---
SELECT 'Income' as source, fld_type, fld_amount, ta.fld_account as account, fld_date, tbl_revenue.fld_description as fld_traninfo, tbl_revenue.fld_created as created
FROM tbl_revenue JOIN tbl_accounts as ta on tbl_revenue.fld_account_id = ta.fld_id
UNION
SELECT 'Expense' as source, fld_type, fld_amount, tae.fld_account, fld_date, tbl_payment.fld_description as fld_traninfo, tbl_payment.fld_created as created
FROM tbl_payment JOIN tbl_accounts as tae on tbl_payment.fld_account_id = tae.fld_id
Is there any way to use query builder in this query?
And second question, you can see I created a virtual column named 'source', i want to filter this column using where clause with append this query like below
WHERE source like "%a%" limit(10,0)
But this returns that I don't have any column name 'source', how can I filter this column?
Any help is appreciated.
there is a way to do that but its a bit hacky because codeigniter's querybuilder adds an auto SELECT statement to the query if you didn't specify it by yourself
In order to get what you want, you've to split your select statements in 2 queries and add the where clause to this query
Something like that should work:
$strQuery1 = $this->db
->select('income as source, fld_type, fld_amount, ta.fld_account as account, fld_date, tbl_revenue.fld_description as fld_traninfo, tbl_revenue.fld_created as created')
->from('tbl_revenue')
->join('tbl_accounts as ta', 'tbl_revenue.fld_account_id = ta.fld_id')
->get_compiled_select();
$strQuery2 = $this->db
->select('Expense as source, fld_type, fld_amount, ta.fld_account as account, fld_date, tbl_revenue.fld_description as fld_traninfo, tbl_revenue.fld_created as created')
->from('tbl_payment')
->join('tbl_accounts as ta', 'tbl_revenue.fld_account_id = ta.fld_id')
->get_compiled_select();
$strWhere = substr($this->db->like('source', 'a', 'both')->get_compiled_select(), 8);
$query = $this->db->query($strQuery1.' UNION '.$strQuery2.$strWhere);

Consults with subqueries and use of regexp

I am trying to identify users that can receive medicines produce interactions. For that I have used this code:
SELECT c.user, COUNT(DISTINCT c.user)
FROM mytable AS c
JOIN (SELECT id_beneficiario, mes
FROM mytable
WHERE codigo_atc REGEXP 'C01BD01|N06AA09|J01FA10|J01MA02|J01FA09|N05AH02|L01XE06|R06AA02|A03FA03|
L04AA27|J02AC01|N06AB03|C03CA01|N05AD01|C03AA03|J02AB02|J01MA12|N05AN01|J01XD01|J05AE04|L01XE08|
N05AH03|N05AH04|N05AX08|J05AE03|J05AE01|C07AA07|L04AD02|M03BX02|N06AX05|J01EE03') AS d
ON c.user = d.user AND c.mes = d.mes
WHERE (c.codigo_atc REGEXP 'C01BD01|N06AA09|J01FA10|J01MA02|J01FA09|N05AH02|L01XE06|R06AA02|A03FA03|
L04AA27|J02AC01|N06AB03|C03CA01|N05AD01|C03AA03|J02AB02|J01MA12|N05AN01|J01XD01|J05AE04|L01XE08|
N05AH03|N05AH04|N05AX08|J05AE03|J05AE01|C07AA07|L04AD02|M03BX02|N06AX05|J01EE03')
GROUP BY c.user;
I am working local and the consult take too much time and apper the next Error: Error code: 2013. Lost conection to MYSQL server during query. Would be possible optimize my code to avoid the error?
Can this work for you?
WHERE codigo_atc IN ('C01BD01','N06AA09','J01FA10','J01MA02','J01FA09',
'N05AH02','L01XE06','R06AA02','A03FA03','L04AA27',
'J02AC01','N06AB03','C03CA01','N05AD01', etc)
This IN clause will return true if codigo_atc matches any of the values in the (list).
SQL is far better at set logic than it is at regular expression matching.
You can try with a in instead of a regexp..
Could be this is more performant
SELECT c.user, COUNT(DISTINCT c.user)
FROM mytable AS c
JOIN (SELECT id_beneficiario, mes
FROM mytable
WHERE codigo_atc IN ('C01BD01','N06AA09','J01FA10','J01MA02','J01FA09','N05AH02','L01XE06','R06AA02','A03FA03','
L04AA27','J02AC01','N06AB03','C03CA01','N05AD01','C03AA03','J02AB02','J01MA12','N05AN01','J01XD01','J05AE04','L01XE08','
N05AH03','N05AH04','N05AX08','J05AE03','J05AE01','C07AA07','L04AD02','M03BX02','N06AX05','J01EE03') AS d
ON c.user = d.user AND c.mes = d.mes
WHERE c.codigo_atc IN ('C01BD01','N06AA09','J01FA10','J01MA02','J01FA09','N05AH02','L01XE06','R06AA02','A03FA03','
L04AA27','J02AC01','N06AB03','C03CA01','N05AD01','C03AA03','J02AB02','J01MA12','N05AN01','J01XD01','J05AE04','L01XE08','
N05AH03','N05AH04','N05AX08','J05AE03','J05AE01','C07AA07','L04AD02','M03BX02','N06AX05','J01EE03')
GROUP BY c.user;
but if you explain your related table schema and what you want obtain could is possible write a more simple query

Is this a legal SQL query?

I have a schema like this
...
Event(Name, Date, TotalSeats)
Reservation(EventName, Date, NumSeats)
...
I want to extract the total number of seats available for each event, is the following query a legal way to do it?
SELECT R.EventName, (SELECT TotalSeats
FROM Event
WHERE Name = R.EventName) - SUM( NumSeats )
FROM Reservation R
GROUP BY EventName;
The more traditional way to write this query would use join:
SELECT r.EventName, e.TotalSeats - SUM( r.NumSeats )
FROM Reservation r JOIN
Event e
ON e.Name = r.EventName
GROUP BY r.EventName, e.TotalSeats;
Your version should work in MySQL, assuming there are no duplicates in the Event table.
The query which you have written in your sub-query..
SELECT TotalSeats FROM Event WHERE Name = R.EventName
can consist of more than one records.. so in that case this query will return error..

Nested MySQL query?

I have this MySQL statement which works fine:
SELECT claim_items.item_id, claim_items.quantity*items_rate.rate as per_item
FROM claim_items, items_rate
WHERE claim_items.claim_id = 1 AND claim_items.item_id = items_rate.items_id
However what I want to do is to get the sum of the per_item field generated in the MySQL statement. Is it possible to do a nested statement to do that? I know I could create a view and then do it, but would prefer to do it in one statement.
Thanks for your help, much appreciated!
select t.id, SUM(t.per_item)
from
(
SELECT claim_items.item_id as id, claim_items.quantity*items_rate.rate as per_item
FROM claim_items, items_rate
WHERE claim_items.claim_id = 1 AND claim_items.item_id = items_rate.items_id
) t
group by t.id
Hope this should help.
If you just want the sum over all rows you can do it like that (using explicit joins for better readability):
SELECT SUM( claim_items.quantity * items_rate.rate )
FROM claim_items
JOIN items_rate ON ( items_rate.items_id = claim_items.item_id )
WHERE claim_items.claim_id = 1