Sorting and grouping a join result? [duplicate] - mysql

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 4 years ago.
I have the following query
SELECT DISTINCT XCS_TASK.WORKFLOW_ID,
XCS_TASK.COMPLETED_BY,
XCS_WORKFLOW.OBJECT_KEY,
XCS_WORKFLOW.OBJECT_TYPE_ID,
XCS_WORKFLOW.END_DATE_TIME,
XCS_WORKFLOW.START_DATE_TIME
FROM `XCS_TASK`
inner JOIN XCS_WORKFLOW ON
XCS_TASK.WORKFLOW_ID = XCS_WORKFLOW.WORKFLOW_ID
WHERE TASK_TYPE_ID = 124
GROUP BY XCS_WORKFLOW.OBJECT_KEY
ORDER BY XCS_WORKFLOW.START_DATE_TIME DESC
The problem is that I want to get the latest record for that OBJECT_KEY. I know above query is wrong because it groups by and then sorts the result of it. I looked in using the MAX(DATE) function but I couldn't get it to work in this scenario. Any help or pointers would be appreciated.

You could try joining the aggregated result for OBJECT_KEY and max date (eg: start_date_time)
SELECT
XCS_TASK.WORKFLOW_ID,
XCS_TASK.COMPLETED_BY,
XCS_WORKFLOW.OBJECT_KEY,
XCS_WORKFLOW.OBJECT_TYPE_ID,
XCS_WORKFLOW.END_DATE_TIME,
XCS_WORKFLOW.START_DATE_TIME
FROM `XCS_TASK`
INNER JOIN XCS_WORKFLOW ON XCS_TASK.WORKFLOW_ID = XCS_WORKFLOW.WORKFLOW_ID
INNER JOIN (
SELECT
XCS_WORKFLOW.OBJECT_KEY,
MAX( XCS_WORKFLOW.START_DATE_TIME ) max_date
FROM XCS_WORKFLOW
GROUP BY OBJECT_KEY
) t ON t.OBJECT_KEY = XCS_WORKFLOW.OBJECT_KEY
AND XCS_WORKFLOW.OBJECT_KEY = t.max_date
WHERE TASK_TYPE_ID = 124

Related

MySQL - Run distinct command on certain columns [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 2 years ago.
I'm trying to run a distinct on four columns in the query below:
select
full_records.id,
full_records.domain_id,
subdomains.name as subdomain_name,
types.name as type_name,
changelog.content as content,
changelog.changed_on
from full_records
inner join subdomains on full_records.subdomain_id = subdomains.id
inner join types on full_records.type_id = types.id
inner join changelog on full_records.id = changelog.full_record_id
where
full_records.domain_id = 2
order by changelog.changed_on desc
and this returns the following:
I'm not sure how to go about altering the query so that it only returns the records that are unique across these four fields.
full_records.domain_id,
subdomains.name as subdomain_name,
types.name as type_name,
changelog.content as content
So if they were unique across those four fields, the rows 2, 3, 4 and 7 would not be in the results. It's basically to identify the latest change for a domain record. Any help would be really appreciated. Thanks.
One pretty simple method is row_number():
with cte as (
select fr.id, fr.domain_id, sd.name as subdomain_name,
t.name as type_name, cl.content, cl.changed_on
from full_records fr join
subdomains sd
on fr.subdomain_id = sd.id join
types t
on fr.type_id = t.id join
changelog cl
on fr.id = cl.full_record_id
where fr.domain_id = 2
)
select cte.*
from (select cte.*,
row_number() over (partition by domain_id, subdomain_name, type_name, content
order by changed_on desc
) as seqnum
from cte
) cte
where seqnum = 1;
Note that I added table aliases so the query is easier to write and to read.

when I add COUNT in the WHERE clause it produces an error but works well in Select [duplicate]

This question already has answers here:
use mysql SUM() in a WHERE clause
(4 answers)
Closed 2 years ago.
Trying to understand why this code produces a result but when I add COUNT(IdCritique) in WHERE it returns an error???
SELECT Titre, ROUND(AVG(Etoiles)) AS Moyenne, COUNT(IdCritique) AS Critiques2020
FROM Film
JOIN Critique
ON FilmID = IdFilm
JOIN Plateforme
ON PformeID = IdPforme
WHERE YEAR(Date) = "2020"
GROUP BY FilmID;
Try like this -
SELECT Titre, ROUND(AVG(Etoiles)) AS Moyenne, COUNT(IdCritique) AS Critiques2020
FROM Film JOIN Critique ON FilmID = IdFilm
JOIN Plateforme ON PformeID = IdPforme
WHERE YEAR(Date) = "2020"
GROUP BY FilmID
having COUNT(IdCritique)= your condition

JOIN with WHERE from JOIN [duplicate]

This question already has answers here:
Can you use an alias in the WHERE clause in mysql?
(5 answers)
Closed 3 years ago.
I have multiple tables with data on some clients. What I want to achieve is to output the amount that a certain client was billed for, in the first month he was billed.
So I run the code similar to the one bellow:
SELECT company,clientid,COALESCE (signed.value,reactivated.value) as 'Activation' , Amount FROM `tblclients`
LEFT JOIN tblcustomfieldsvalues as signed ON tblclients.clientid = signed.relid and signed.fieldid = 5
LEFT JOIN tblcustomfieldsvalues as reactivated ON tblclients.userid = reactivated.relid and reactivated.fieldid = 27
LEFT JOIN (
SELECT clientid,sum(total) as Amount FROM tblinvoices
WHERE month(invoicedate)=month(Activation) Group by clientid) as f on tblclients.clientid = f.clientid
My problem is that when I do the last join it gives an error : Unknown column 'Activation' in 'where clause'.
If I switch that to current_date the rest of the query works.
Any idea on how to make this work ?
Later edit: I might have oversimplified the query, I also have a COALESCE
You can try below -
SELECT company,clientid,activated.value as Activation , Amount
FROM `tblclients`LEFT JOIN tblcustomfieldsvalues as signed ON tblclients.clientid = signed.relid and signed.fieldid = 5
LEFT JOIN
( SELECT clientid,sum(total) as Amount
FROM tblinvoices Group by clientid
) as f on tblclients.clientid = f.clientid and month(invoicedate)=month(Activation)

Getting First Order Date for Each Customer [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 4 years ago.
this one is driving me to drink so I would love some help.
I've got a table with:
act_Address, act_OrderID, act_Date
I'm trying to get the first act_Date for each address we shipped to.
Here's what I've tried but it's been running now for well over an hour so I'm thinking this isn't going to work...
SELECT c.act_Address,
(SELECT o.act_OrderID
FROM tbl_Activity o
WHERE c.act_Address = o.act_Address
ORDER BY o.act_Date
LIMIT 1) AS order_id,
(SELECT d.act_Date
FROM tbl_Activity d
WHERE c.act_Address = d.act_Address
ORDER BY d.act_Date
LIMIT 1) as order_date
FROM tbl_Activity c
I've got to be doing something very wrong, doesn't seem like getting the first date for an address would be that hard, but I'm not that smart.
Your query uses two correlated subqueries to get act_Date and act_OrderID values. Each subquery is executed once for every record of tbl_Activity.
You can use:
SELECT act_Address, MIN(act_Date) AS fist_Date
FROM tbl_Activity
GROUP BY act_Address
to get the first date per address. Then you can use the above query as a derived table and join back to the original table to get the rest of the fields:
SELECT t1.act_Address, t1.act_OrderID, t1.act_date
FROM tbl_Activity AS t1
JOIN (
SELECT act_Address, MIN(act_Date) AS fist_Date
FROM tbl_Activity
GROUP BY act_Address
) AS t2 ON t1.act_Address = t2.act_Address AND t1.act_Date = t2.first_Date
I also propose placing a composite index on (act_Address, act_Date).
You can do this by GROUP BY in a subselect:
SELECT a.act_Address, a.act_OrderID, a.act_Date
FROM (
SELECT a2.act_Address addr, MIN(a2.act_Date) mindate FROM tbl_Activity a2
GROUP BY a2.act_Address
) g, tbl_Activity a
WHERE a.act_Address = g.addr AND a.act_Date = g.mindate;

MySQL select distinct records [duplicate]

This question already has answers here:
MySQL query, MAX() + GROUP BY
(7 answers)
Closed 9 years ago.
I'm trying to write a query that will pull out the "best" record from a list of values:
SELECT s.swimmerName, r.resultTimeText, r.resultAgeGroup, r.resultEventID, v.venueName
FROM tblResults r
JOIN tblEvents e ON e.eventID = r.resultEventID
JOIN tblSwimmers s ON r.resultSwimmerID = s.swimmerID
JOIN tblVenues v ON e.resultVenueID = v.venueID
WHERE s.swimmerGender = %s
AND r.resultStroke = %s
GROUP BY s.swimmerName
This selects all of my records but people are listed twice with different times (a consequence of the DISTINCT I know). What would be the best way to select the best time for each person?
You can use mysql's quirky grouping to help you:
SELECT * FROM (
SELECT s.swimmerName, r.resultTimeText, r.resultAgeGroup, r.resultEventID, v.venueName
FROM tblResults r
JOIN tblEvents e ON e.eventID = r.resultEventID
JOIN tblSwimmers s ON r.resultSwimmerID = s.swimmerID
JOIN tblVenues v ON e.resultVenueID = v.venueID
WHERE s.swimmerGender = %s
AND r.resultStroke = %s
ORDER BY 2) x
GROUP BY swimmerName
ORDER BY 2
This works by first ordering the data fastest to slowest, then grouping by name. In myswl (only) grouping by not all non-aggregated columns has the effect of filtering only the first row encountered for each unique combination of grouped by colums.