How to select only the last date row of a joined Table? - mysql

I am joining Table B into A. Table A has the basic information I want to retrieve and also the unique ID.
Table B has multiple rows for each ID with another column with Dates. Now I only want to select the last Date of Table B and join in into A.
I found the MAX() function of SQL but it says the other fields are not in the GROUP BY clause or an aggregation function.
This is my (simplified) query:
SELECT
MAX("B"."ENDDATE") AS FINALEND,
"A."ID",
"A"."COLOR",
"A"."MAKE",
"A"."WHEELS",
FROM "A"
JOIN "B" ON "A"."ID" = "B"."ID"
My expected result is for each ID a row with the basic information from Table A and the last Date from all matching rows from Table B. My result now is multiple rows for every row in B.
Do I need to add a GROUP BY for ever other column? Or what am I missing?
Thanks for any input :)

On MySQL 8+, we can use ROW_NUMBER here:
WITH cte AS (
SELECT a.*, b.ENDDATE,
ROW_NUMBER() OVER (PARTITION BY a.ID ORDER BY b.ENDDATE DESC) rn
FROM A a
INNER JOIN B b ON b.ID = a.ID
)
SELECT ID, COLOR, MAKE, WHEELS, ENDDATE AS FINALEND
FROM cte
WHERE rn = 1;
On earlier versions of MySQL, we can join to a subquery which finds the latest record for each ID in the B table:
SELECT a.ID, a.COLOR, a.MAKE, a.WHEELS, b1.ENDDATE AS FINALEND
FROM A a
INNER JOIN B b1 ON b1.ID = a.ID
INNER JOIN
(
SELECT ID, MAX(ENDDATE) AS MAXENDDATE
FROM B
GROUP BY ID
) b2
ON b2.ID = b1.ID AND b2.MAXENDDATE = b1.ENDDATE;

Related

Get latest date after joining with another table and grouping by some other column mysql

I have 2 tables like this:
table_1 :
table_2 :
I want to join these two tables and get the latest rank of all the ids.
I got upto this query:
SELECT a.Name, b.Rank
FROM table_1 a
INNER JOIN table_2 b
ON a.id = b.id
GROUP BY id
This gives me the rank based for each id, but not the rank on the latest date.
I'm not sure how to do this. Any help is appreciated.
Please note that I have 100s of different dates for same user ids in table_2, and when joined with table_1, should result in latest rank. This is my requirement.
I suspect that you are using MySQL 5.7 or earlier, so we can use a join approach here:
SELECT a.Name, b1.Rank
FROM table_1 a
INNER JOIN table_2 b1 ON b1.id = a.id
INNER JOIN
(
SELECT id, MAX(Date) AS MaxDate
FROM table_2
GROUP BY id
) b2
ON b2.id = b1.id AND b2.MaxDate = b1.Date;
Note that from MySQL version 8 and onwards RANK is a reserved MySQL keyword and would need to be escaped in backticks or double quotes in order to use it as an alias. But, on 5.7 or earlier, the above code should work as is.

SQL Select two records if they have certain time difference of column A and have same column B value

I have 14000 records in my sql table. They have columns ID, test_subject_id and date_created. I want to fetch all the records that have been created within a time difference of 3 minutes(difference in date_created values) and both records should have the same test_subject_id.
You should use a self join, I assume inner join is what will work for you:
SELECT a.ID, a.date_created, b.ID, b.date_created
FROM accounts a
INNER JOIN accounts b
ON a.test_subject_id = b.test_subject_id
AND TIMESTAMPDIFF(MINUTE,a.date_created,b.date_created) = 3
Note: TIMESTAMPDIFF is used assuming date_created has type datetime, details here.
You can use EXISTS:
SELECT t1.*
FROM tablename t1
WHERE EXISTS (
SELECT 1
FROM tablename t2
WHERE t2.test_subject_id = t1.test_subject_id
AND ABS(TIMESTAMPDIFF(SECOND, t1.date_created, t2.date_created)) <= 180
)
ORDER BY t1.test_subject_id, t1.date_created;

How to get the last row in the table using group by with Order by DESC?

I have two tables,
table one name (tbl_brands) with these columns:
and second table name (tbl_loader_attachment) with these columns:
I used this MySQL code below to sort by DESC:
SELECT tbl_loader_attachment.*, tbl_brands.* FROM tbl_loader_attachment
INNER JOIN tbl_brands ON(tbl_brands.b_id=tbl_loader_attachment.b_id)
GROUP BY tbl_loader_attachment.b_id ORDER BY tbl_loader_attachment.la_id DESC
When I execute my code select the first row appear (test1) I want to select the last row get (test4)
One approach uses a GROUP BY query:
SELECT tla1.*, tb.*
FROM tbl_brands tb
INNER JOIN tbl_loader_attachment tla1
ON tb.b_id = tla1.b_id
INNER JOIN
(
SELECT b_id, MAX(la_id) AS max_la_id
FROM tbl_loader_attachment
GROUP BY b_id
) tla2
ON tla1.b_id = tla2.b_id AND
tla1.la_id = tla2.max_la_id;
If you are using MySQL 8+ (or should a future reader of this question be using MySQL 8+), then another option here is to use ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY b_id ORDER BY la_id DESC) rn
FROM tbl_loader_attachment
)
SELECT tla.*, tb.*
FROM tbl_brands tb
INNER JOIN cte tla ON tb.b_id = tla.b_id
WHERE tla.rn = 1;

how to group by a field that has both select and count

I am wondering how to group by a field that has both a select count() and count() statement. I know that we have to put all select fields in group by but it wont let me do so because of the second count() statement in the field.
create table C as(
select a.id, a.date_id,
(select count(b.hits)*1.00 where b.hits >= '9')/count(b.hits) AS percent **<--error here
from A a join B b
on a.id = b.id
group by 1,2,3) with no data primary index(id);
This is my error:
[SQLState HY000] GROUP BY and WITH...BY clauses may not contain
aggregate functions. Error Code: 3625
When i add a select to the second count in the third line only get 1 or 0 which is not right.
`((select count(b.hits)*1.00 where b.hits >= '9')/(select count(b.hits))) AS` percent
Do i need to do a self join instead or is there any way i can just use nested queries?
You need to fix the group by. But, you can probably simplify the query as:
create table C as
select a.id, a.date_id,
avg(b.hits >= 9) as percent
from A a join
B b
on a.id = b.id
group by a.id, a.date_id
with no data primary index(id);
It looks like you only need to group on 2 columns, not 3, plus you shouldn't need a sub-select:
create table C as(
select a.id, a.date_id,
SUM(CASE WHEN b.hits >= '9' THEN 1 ELSE 0 END)/COUNT(b.hits) AS percent
from A a join B b
on a.id = b.id
group by 1,2) with no data primary index(id);

using distinct rows for join mysql

Suppose I have table A, B
ID in A is unique but in table B, ID is not unique
I want to SELECT DISTINCT ID
query 1:
SELECT DISTINCT ID FROM A a LEFT JOIN B b ON a.ID = B.ID WHERE ...
query 2:
SELECT DISTINCT ID FROM A WHERE ID IN (SELECT DISTINCT ID FROM B where ...)
or
SELECT DISTINCT ID FROM A a LEFT JOIN (SELECT DISTINCT ID FROM B) b ON a.ID = B.ID WHERE ...
The end result is same but
what happens in query 1 is the space of temp table is more as multiple rows from table B will come with repeated ID
In query 2 i am able to optimize space and further processing as it will have limited rows with all distinct ID's
Isn't there any way to use DISTINCT rows from table B using join and avoiding subqueries?
Actually I have even table C which I will join with this, so I need to care for the number of rows taking part in 2nd join when taking join further with table C.
SELECT DISTINCT ID FROM A a LEFT JOIN (SELECT DISTINCT ID FROM B) b ON a.ID = B.ID WHERE ...
Is this what you want?
Edit so the answer is a bit more visible:
Since your A is unique, but B isn't you can just swap the values :
SELECT DISTINCT ID FROM B b LEFT JOIN A a on a.ID = b.ID WHERE...