I have following 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
I tried this:
$query = HireScreening::find()
->select(["hs.resume_id","MAX(hs.created_date) AS MaxDateTime"])
->innerJoin('hire_screening as hs','hs.resume_id = hire_screening.resume_id')
->where(['hire_screening.created_date' => 'MaxDateTime'])
->orderBy(['(hs.created_date)' => SORT_DESC])
->groupBy(['hs.resume_id']);
When I use group by the result shows the first values of each 'resume_id' in the order that stored in the table. I just need the most latest distinct resume_id 's according to created_date.
How can I implement this query in yii2 search model? Please help.
If you want to execute the raw sql query means, then you can use
createCommand function. But it will return the array so in grid you should use array data provider.
$array= Yii::$app->db->createCommand("
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")->queryAll();
Related
I have been having some troubles getting my head around achieving the below.
I have an 'applications' table and a 'application_logs' table. I am attempting to select all the applications where the 'type' is equal to 'test' and then join the 'application_logs' table and retrieve only the first log entry for the application.
One of the queries I tried and understood most was: (whilst this didn't fail it looked like an endless loop and completed the query.
SELECT applications.id FROM applications JOIN application_logs ON application_logs.application_id =
(
SELECT application_logs.id FROM application_logs
WHERE application_logs.application_id = applications.id
ORDER BY id DESC
LIMIT 1
)
WHERE type = 'test';
There were some other queries (using CROSS APPLY/distinct) I attempted but they didn't make sense to me and didn't look like they were trying to achieve the same thing. I appreciate all the help :)
There are many ways to achieve this in standard SQL. A lateral join (CROSS APPLY) is the first to come to mind, but MySQL doesn't support it. Another would be FETCH FIRST ROWS WITH TIES to get all latest application logs, but MySQL doesn't support it (and its counterpart LIMIT doesn't have a ties clause either). If you are only interested in the application ID alone (as shown in your query) one could even combine this with an INTERSECT operation, but MySQL doesn't support it.
After all you want to find out the maximum log ID per application ID. As of MySQL 8 you can do this on-the-fly:
select *
from applications a
left join
(
select
application_logs.*,
max(id) over (partition by application_id) as max_application_id
from application_logs
) al on al.application_id = a.id and al.application_id = al.max_application_id
where a.type = 'test';
In earlier vesions you would do this in separate steps. One way would be this:
select *
from applications a
left join application_logs al
on al.application_id = alm.application_id
and (al.application_id, al.id) in
(
select application_id, max(id)
from application_logs
group by application_id
)
where a.type = 'test';
Another is your own query, where you only got confused with the IDs:
SELECT *
FROM applications a
JOIN application_logs al ON al.id =
(
SELECT almax.id
FROM application_logs almax
WHERE almax.application_id = a.id
ORDER BY almax.id DESC
LIMIT 1
)
WHERE a.type = 'test';
try this
SELECT
a.*, c.*
FROM
applications a
INNER JOIN (
SELECT
al.application_id AS application_id,
MAX(al.id) AS al_id
FROM
application_logs al
GROUP BY
al.application_id
) c ON a.id = c.application_id
WHERE
a.type = 'test';
To get the first entry from application_logs table with respect to application_id. You need to use Row_Number Over (partition by order by ).
SELECT *
FROM applications A
LEFT JOIN (
SELECT Id AS applications.id
FROM (
SELECT ROW_NUMBER() OVER (Partition By applications.id ORDER BY application_logs.id) as R, application_logs.id, applications.id
FROM application_logs
) AS S
WHERE R = 1
) AS L ON L.applications.id = A.applications.id
Try this -
SELECT a.id, ay.*
FROM applications AS a
INNER JOIN (
SELECT al.application_id, min(al.id) as Min_Id
FROM application_logs AS al
GROUP BY al.application_id
) AS ax ON ax.application_id = a.id
INNER JOIN application_logs AS ay ON ay.id = ax.id
WHERE a.type = 'test';
Your query suggests that "first" means the largest id. (Colloquially, I would expect "first" to mean the smallest id or earliest chronologically.)
I usually recommend a correlated subquery for the filtering. It is worth testing if this is faster than other methods:
select . . .
from applications a join
application_logs al
on al.application_id = a.id
where a.type = 'test' and
al.id = (select max(al2.id)
from application_logs al2
where al2.application_id = al.application_id
);
The optimal indexes for performance are:
application(type, id)
application_logs(application_id, id)
I have a question about a SQL, I have never worked with the select sub and I ended up getting lost with it.
Meu SQL:
SELECT CLI.id, CLI.nome, CLI.senha, CLI.email, CLI.cpf, CLI.celular, CLI.data_nasc, CLI.genero, CLI.data_cadastro, CLI.status, CLI.id_socket, ATEN.mensagem, ARQ.nome AS foto, ATEN.data_mensagem
FROM ut_clientes AS CLI
LEFT JOIN ut_arquivos AS ARQ ON (ARQ.id_tipo = CLI.id AND ARQ.tipo = "ut_clientes")
INNER JOIN ut_atendimentos AS ATEN ON (ATEN.id_usuario_envio = CLI.id)
WHERE ATEN.id_usuario_envio != 59163
GROUP BY CLI.id
ORDER BY ATEN.data_mensagem
DESC
Well, what I would like to do is group the messages according to the customer ID and bring only the last message recorded in the database according to the data_mensagem.
I have tried in many ways but always the last one that is displayed is the first message inserted in DB.
If anyone can help me, I'll be grateful. Thank you guys!
This may help you... I am using a join to a pre-query (PQ alias). This query just goes to your messages and grabs the client ID and the most recent based on the MAX(). By doing the group by here, it will at most return 1 record per client. I also have the WHERE clause to exclude the one ID you listed.
From THAT result, you do a simple join to the rest of your query.
SELECT
CLI.id,
CLI.nome,
CLI.senha,
CLI.email,
CLI.cpf,
CLI.celular,
CLI.data_nasc,
CLI.genero,
CLI.data_cadastro,
CLI.status,
CLI.id_socket,
ATEN.mensagem,
ARQ.nome AS foto,
PQ.data_mensagem
FROM
ut_clientes AS CLI
LEFT JOIN ut_arquivos AS ARQ
ON CLI.id = ARQ.id_tipo
AND ARQ.tipo = "ut_clientes"
INNER JOIN
( select
ATEN.id_usuario_envio,
MAX( ATEN.data_mensagem ) as MostRecentMsg
from
ut_atendimentos AS ATEN
where
ATEN.id_usuario_envio != 59163
group by
ATEN.id_usuario_envio ) PQ
ON CLI.id = PQ.id_usuario_envio
GROUP BY
CLI.id
ORDER BY
PQ.data_mensagem DESC
I am trying to bring through the site.Site_Name, for each hive.hiveno and it's max(hiverdg.invdate). Running the code below doesn't work because site.Site_Name is not aggrigated. If I add site.Site_Name to the Group By, the code runs, but the ouput displays the results repeated, once for each site.Site_Name
select site.Site_Name ,hive.hiveno, max(hiverdg.invdate)
from hiverdg
inner join hive
on hiveRdg.hive_Link = hive.hive_Link
inner join Customer
on customer.Customer_Link = hive.Customer_Link
inner join site
on site.Customer_Link = customer.Customer_Link
where
(hiverdg.xtype = 'N'
and customer.CustomerName = 'Cust1')
or
(hiverdg.xtype = 'A'
and customer.CustomerName = 'Cust1')
group by hive.hiveno
The easiest way to do this, with your query, is the substring_index()/group_concat() trick:
select substring_index(group_concat(s.Site_Name order by rdg.invdate desc separator '|'
), '|', 1
) as SiteName,
h.hiveno, max(rdg.invdate)
from hiverdg rdg inner join
hive h
on rdg.hive_Link = h.hive_Link inner join
Customer c
on c.Customer_Link = h.Customer_Link inner join
site s
on s.Customer_Link = c.Customer_Link
where rdg.xtype in ('N', 'A') and c.CustomerName = 'Cust1')
group by h.hiveno;
I also made the following changes to your query:
Introduced table aliases, to make the query easier to write and to read.
Changed the where to use in, simplifying the logic.
I've created sqlfiddle to try and get my head around this http://sqlfiddle.com/#!2/21e72/1
In the query, I have put a max() on the compiled_date column but the recommendation column is still coming through incorrect - I'm assuming that a select statement will need to be inserted on line 3 somehow?
I've tried the examples provided by the commenters below but I think I just need to understand this from a basic query to begin with.
As others have pointed out, the issue is that some of the select columns are neither aggregated nor used in the group by clause. Most DBMSs won't allow this at all, but MySQL is a little relaxed on some of the standards...
So, you need to first find the max(compiled_date) for each case, then find the recommendation that goes with it.
select r.case_number, r.compiled_date, r.recommendation
from reporting r
join (
SELECT case_number, max(compiled_date) as lastDate
from reporting
group by case_number
) s on r.case_number=s.case_number
and r.compiled_date=s.lastDate
Thank you for providing sqlFiddle. But only reporting data is given. we highly appreciate if you give us sample data of whole tables.
Anyway, Could you try this?
SELECT
`case`.number,
staff.staff_name AS ``case` owner`,
client.client_name,
`case`.address,
x.mx_date,
report.recommendation
FROM
`case` INNER JOIN (
SELECT case_number, MAX(compiled_date) as mx_date
FROM report
GROUP BY case_number
) x ON x.case_number = `case`.number
INNER JOIN report ON x.case_number = report.case_number AND report.compiled_date = x.mx_date
INNER JOIN client ON `case`.client_number = client.client_number
INNER JOIN staff ON `case`.staff_number = staff.staff_number
WHERE
`case`.active = 1
AND staff.staff_name = 'bob'
ORDER BY
`case`.number ASC;
Check below query:
SELECT c.number, s.staff_name AS `case owner`, cl.client_name,
c.address, MAX(r.compiled_date), r.recommendation
FROM case c
INNER JOIN (SELECT r.case_number, r.compiled_date, r.recommendation
FROM report r ORDER BY r.case_number, r.compiled_date DESC
) r ON r.case_number = c.number
INNER JOIN client cl ON c.client_number = cl.client_number
INNER JOIN staff s ON c.staff_number = s.staff_number
WHERE c.active = 1 AND s.staff_name = 'bob'
GROUP BY c.number
ORDER BY c.number ASC
SELECT
case.number,
staff.staff_name AS `case owner`,
client.client_name,
case.address,
(select MAX(compiled_date)from report where case_number=case.number),
report.recommendation
FROM
case
INNER JOIN report ON report.case_number = case.number
INNER JOIN client ON case.client_number = client.client_number
INNER JOIN staff ON case.staff_number = staff.staff_number
WHERE
case.active = 1 AND
staff.staff_name = 'bob'
GROUP BY
case.number
ORDER BY
case.number ASC
try this
Hi I have the following query from a previous question and need to convert it to DQL for Doctrine 1.2. However it turns out that DQL does not support subqueries in joins.
SELECT * FROM contact c
LEFT JOIN
(SELECT a1.contact_id, a1.date, a1.activity_type_id FROM activity a1
JOIN (SELECT contact_id, MAX(DATE) DATE FROM activity GROUP BY contact_id) a2
ON a1.contact_id = a2.contact_id AND a1.date = a2.date
) a
ON c.id = a.contact_id
WHERE a.activity_type_id = 2;
I'm trying to figure out how to do this another way without resorting to multiple queries.
Thanks.
Using doctrine, you should not nest subqueries into where condition using raw sql. You will get into trouble in more complex scenarios. Instead use createSubquery to explicitly tell doctrine about the subquery, let doctrine compile it to DQL and then nest it into your where condition. So your query should look something like this:
$q->from('Contact c')
->leftJoin('c.Activity a')
;
$subquery = $q->createSubquery()
->select("a1.contact_id, MAX(a1.date) a1.date")
->from("Activity a1")
->groupby("a1.contact_id")
;
$q->where('ROW (c.id, date) IN ('.$subquery->getDql().')')
->andWhere('a.activity_type_id = ?', $filterActivityTypeId)
;
Another example can be found here:
https://www.philipphoffmann.de/2012/08/29/a-bulletproof-pattern-for-creating-doctrine-subqueries-of-any-complexity/
Final query:
SELECT * FROM contact c
LEFT JOIN activity ON c.id = contact_id
WHERE ROW (c.id,DATE) IN (SELECT contact_id, MAX(date) date FROM activity GROUP BY contact_id)
AND activity_type_id = 2
Final DQL:
$q->from('Contact c')
->leftJoin('c.Activity a')
->where('ROW (c.id, date) IN (SELECT a1.contact_id, MAX(a1.date) a1.date FROM Activity a1 GROUP BY a1.contact_id)')
->andWhere('a.activity_type_id = ?', $filterActivityTypeId);