Query a table with limited results, based on another table - mysql

Let's assume I have tbl2, with a foreign key to another table (tbl1). For each record in the tbl1, we can have multiple or no records in tbl2.
I want to have only one record from tbl2 (the last record, based on time), which matches with a record on tbl1. The following query only returns one record:
select * from tbl2
where fk in (select id from tbl1 where some_criteria)
order by time LIMIT 1 DESC
This query also returns all records from tbl2:
select * from tbl2
where fk in (select id from tbl1 where some_criteria)
order by time DESC
I wanna have a row for each record from select id from tbl1 where some_criteria, having all details from the latest record exists in tbl2.

You want a lateral join, available since MySQL 8.0.14:
select *
from tbl1
left outer join lateral
(
select *
from tbl2
where tbl2.fk = tbl1.id
order by time desc
limit 1
) newest_tbl2 on true;
Here is a solution for old MySQL versions: Aggregate the tbl2 by fk to get the maximum time per fk. Then use this result in your joins.
select *
from tbl1
left outer join
(
select fk, max(time) as max_time
from tbl2
group by fk
) mx on mx.fk = tbl1.id
left outer join tbl2 on tbl2.fk = mx.fk and tbl2.time = mx.max_time;

Related

compare one column in table with many columns in another table mysql

I want to compare a column in tbl1 with more than columns in tbl2
to find the matched values my code with one column in tbl2
SELECT * FROM tbl1 WHERE new_pass1 IN(SELECT pass_no1 FROM tbl2)
this code compare with on column in the tbl2
I want with more than column pass_no2 and pass_no3 in tbl2
Just add the other columns to your SELECT:
SELECT *
FROM tbl2
WHERE new_pass1 IN(SELECT pass_no1 FROM tb2) OR
new_pass1 IN(SELECT pass_no2 FROM tb2) OR
new_pass1 IN(SELECT pass_no3 FROM tb2)

Delete records based on another query in mysql

I have a query in MySQL based on which I am finding duplicate records of some columns.
select max(id), count(*) as cnt
from table group by start_id, end_id, mysqltable
having cnt>1;
This above query gives me the max(id) and the count of number of records that have start_id,end_id,mysqltable column values same.
I want to delete all the records that match the max(id) column of the above query
How can I do that?
I have tried like below
delete from table
where (select max(id), count(*) as cnt
from table group by start_id,end_id,mysqltable
having cnt>1)
But Unable to delete records
You can remove duplicate records using JOIN.
DELETE t1 FROM table t1
INNER JOIN
table t2
WHERE
t1.id > t2.id AND t1.start_id = t2.start_id AND t1.end_id = t2.end_id AND t1.mysqltable = t2.mysqltable;
This query keeps the lowest id and remove the highest.
I think so this command should work:
delete from table
where id in
( select max(id) from table
group by start_id, end_id, mysqltable
having count(*) > 1
);

mysql Select row with most recent date per user - make it faster

records in my table are like below:
id |sensor_id|val |audit_date
255245| 1|22.12|2017-02-18 08:26:47
and I want get latest records using this
SELECT `sensor_id`, `val`, `audit_date`
FROM `tests` t1
JOIN (SELECT max(`audit_date`) as audit_date, `sensor_id`
from `tests` group by `sensor_id`) t2
USING (`audit_date`, `sensor_id`)
where `id` > (select max(`id`)-1000 from `tests`)
It takes more than one second; without last "where" - second and half.
"id" is primary key and now indexes.
What I can do to make this query faster?
This query return latest instered record using max() funtion
SELECT t1.sensor_id,val,t1.audit_date
FROM `tests` t1
JOIN (SELECT max(`audit_date`) as audit_date, max(`sensor_id`) as max_sensor_id
FROM `tests` group by `sensor_id`) t2
ON t2.max_sensor_id = t1.sensor_id
AND t2.audit_date =t1.audit_date
You can try if a self-exclusion join would be faster:
SELECT t1.sensor_id, t1.val, t1.audit_date
FROM audit t1
LEFT JOIN audit t2
ON t1.sensor_id = t2.sensor_id
AND t2.audit_date > t1.audit_date
where
t2.id is null
Basically that says return records for which there are no greater audit_dates per sensor_id.

DISTINCT in mysql query removing the records from resultset

DISTINCT in mysql query removing the records from resultset
I have three tables
TBL1 TBL2 TBL3
---- ------ --------
tbl1_id tbl2_id tbl3_id
cid fkcid fkcid
fktbl1_id fktbl2_id
I have query to get records of TBL3
select distinct tbl3.* from TBL3 tbl3
inner join TBL2 tbl2 on tbl2.tbl2_id = tbl3.fktbl2_id and tbl2.fkcid = tbl3.fkcid
inner join TBL1 tbl1 on tbl1.tbl1_id = tbl2.fktbl1_id and tbl2.fkcid = tbl1.cid;
This query gives me around 1000 records.
But when I removes distinct from query it gives me around 1100 records.
There is no duplicate records in table.Also I confirmed that these extra 100 are not duplicate.Please note That these extra 100 records are not found in query with distinct keyword.
Why this query is behaving unexpectedly.Please help me to understand more clearly and correct me if i am making mistake.
Thank you
You have multiple records in tbl1 or tbl2 that map to the same tbl3, and since you're only selecting tbl3.* in your output, DISTINCT removes the duplication. To instead find what the duplicates are, remove the DISTINCT, add a COUNT(*) to the SELECT clause, and add at the end a GROUP BY and HAVING, such as:
select tbl3.*, count(*)
from TBL3 tbl3
inner join TBL2 tbl2 on tbl2.tbl2_id = tbl3.fktbl2_id and tbl2.fkcid = tbl3.fkcid
inner join TBL1 tbl1 on tbl1.tbl1_id = tbl2.fktbl1_id and tbl2.fkcid = tbl1.cid
group by tbl3.tbl3_id, tbl3.fkcid, tbl3.fktbl2_id having count(*) > 1;

Mysql can't join two tables columns into one show

I want to show two columns summarize data.
table1 - count all fields that the id same as the id on the show_users table.
table2 - sum all values that the id same as the id on the show_users table.
This is my query:
SELECT show_users.id, COUNT(`table1`.id) as sum_fields , SUM(`table2`.count) as count_all
FROM `show_users`
LEFT JOIN `table1` ON `show_users`.id = `table1`.id
LEFT JOIN `table2` ON `show_users`.id = `table2`.id
GROUP by show_users.id
ORDER BY sum_fields DESC
The table2 results are fine, but the table1 count isn't correct values...
Why is that?
SELECT show_users.id, COUNT(DISTINCT `table1`.id) as sum_fields , SUM(`table2`.count) as count_all