Simple MYSQL distinct select - mysql

If I have a table with two columns, name and timestamp, and a bunch of rows that will have shared names. How do I select the most recent row of each set of rows that shares the same name?
Thanks!

SELECT name, MAX(timestamp) FROM Table1 GROUP BY name
EDIT: Based on the comment, please try the following:
SELECT name, timestamp, col3, col4
FROM Table1 t1
WHERE timestamp = (SELECT MAX(t2.timestamp)
FROM Table1 t2
WHERE t1.name = t2.name);
Added by Mchl
Version with no dependent subquery (should perform better)
SELECT
t1.name, t1.timestamp, t1.col3, t1.col4
FROM
Table1 AS t1
CROSS JOIN (
SELECT
name, MAX(timestamp) AS timestamp
FROM
Table1
GROUP BY
name
) AS sq
USING (name,timestamp)

Then you need a subquery:
SELECT columns
FROM Table1 t1
WHERE row_id = (SELECT row_id
FROM table1 t2
WHERE t1.name = t2.name
ORDER BY timestamp DESC
LIMIT 1)
GROUP BY name
Edited, forgot the group by name

Related

Get id of the record having Min() value

I have a complex mysql query where one of the Select fields is Min(value). Since all the 'values' are unique, is there also a way to get found min value's row id along?
In other words if we simplify the query to this question, it is like this:
SELECT t1.name, MIN(t2.value) AS minval
FROM table1 t1
LEFT JOIN table2 t2
ON t2.id_user = t1.id
GROUP BY id_user
How can i now know which t2.id was chosen for lowest t2.value for particular user? Thank you!
Use ROW_NUMBER() to find the first value of each id_user
You can replace * with the fields you need
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY t2.id_user ORDER BY t2.value) as rnk
FROM table1 t1
LEFT JOIN table2 t2
ON t2.id_user = t1.id
) as X
WHERE X.rnk = 1
Maybe this simple, dont know how complex your statement is:
SELECT name,value,id
FROM(
SELECT t1.name,t2.value,t2.id
FROM table1 t1
LEFT JOIN table2 t2
ON t2.id_user = t1.id
GROUP BY t2.id,id_user
ORDER BY t1.name,t2.id asc) as test
GROUP BY name;

MySQL select a set of columns with more than one variation in another column

table looks like this:
id group name
1 1 A
2 1 A
3 2 A
4 2 B
5 3 A
I want to select the rows with more than one distinct names in the same group. The result should be the following:
id group name
3 2 A
4 2 B
Any idea how do achieve this?
You can get the groups with aggregation:
select group
from t
group by group
having min(name) <> max(name);
You can get the original rows using join, in, or exists:
select t.*
from t
where t.group in (select group
from t
group by group
having min(name) <> max(name)
);
Note: group is a lousy name for a column because it is a SQL keyword and a MySQL reserved word.
You could do it with a correlated subquery:
SELECT t1.id, t1.group, t1.name
FROM mytable AS t1
WHERE EXISTS (
SELECT * FROM mytable t2
WHERE t2.group=t1.group AND t2.name <> t1.name
);
Or you could do it by counting distinct names in the group:
SELECT t1.id, t1.group, t2.name
FROM mytable AS t1
INNER JOIN (
SELECT t2.group FROM mytable AS t2
GROUP BY t2.group HAVING COUNT(DISTINCT t2.name) > 1
) AS t2 USING (group);

SQL Query to display employee who is a supervisor from employee table

I am in this dilemma: here is a table with records.
The last column has supervisors and it refers to the first column.
How can I select all employees who are supervisors and display for each, first name and last name?
Here is the table
You can use EXISTS to do this(preferred approach)
SELECT *
FROM yourtable t1
WHERE EXISTS (SELECT 1
FROM yourtable t2
WHERE t1.EMPLOYEEID = t2.EMPSUPERVISOR)
using IN operator
SELECT *
FROM yourtable t1
WHERE t1.EMPLOYEEID IN (SELECT t2.EMPSUPERVISOR
FROM yourtable t2)
using JOIN
SELECT t1.*
FROM yourtable t1
JOIN (SELECT DISTINCT EMPSUPERVISOR
FROM yourtable) t2
ON t1.EMPLOYEEID = t2.EMPSUPERVISOR
I would say:
SELECT EMPLNAME , EMPLFNAME
FROM THETABLE
WHERE EMPLOEEID IN (SELECT DISTINCT EMPSUPERVISOR
FROM THETABLE
)
;

Joining three tables such that extra matches are discarded?

How can I write a query to give the results of three tables such that there's only one result per "line"?
The tables are:
T1 (ID, name, IP)
T2 (ID, date_joined)
T3 (ID, address, date_modified)
The relations are:
T1-T2 1:1, T1-T3 1:M - there can be many address rows per ID in T3.
What I want is a listing of all users with the fields above, but IF they have an address, I only want to record ONE (bonus would be if it is the latest one based on T3.date_modified).
So I should end up with exactly the number of records in T1 (happens to be equal to T2 in this case) and no more.
I tried:
select t.ID, t.name, t.IP, tt.ID, tt.date_joined, ttt.ID, ttt.address
from T1 t JOIN T2 tt ON (t.ID = tt.ID) JOIN T3 ttt ON (t.ID = ttt.ID)
And every sensible combination of LEFT, RIGHT, INNER, etc joins I could think of! I keep getting multiple duplicate because of T3
This query should work:
select
t1.ID, t1.name, t1.IP, t2.date_joined, t3x.address
from t1
join t2 on t1.ID = t2.id
left join (
select t3.*
from t3
join (
select id, max(date_modified) max_date
from t3
group by id
) max_t3 on t3.id = max_t3.id and t3.date_modified = max_t3.max_date
) t3x on t1.ID = t3x.id
First you do the normal join between t1 and t2 and then you left join with a derived table (t3x) that is the set of t3 rows having the latest date.
So T2 is actually not relevant here. You just need a way to join from T1 to T3 in a way that gets you at most one T3 row per T1 row.
One way of doing this would be:
select
T1.*,
(select address from T3 where T3.ID=T1.ID order by date_modified desc limit 1)
from T1;
This won't likely be very efficient, being a correlated subquery, but you may not care depending on the size of your dataset.
It's also only good for getting one column from T3, so if you had Address, City, and State, you'd have to figure out something else.
You can use sub query with Top 1 so that u get only one result from T3
here is a sample sql
select * into #T1 from(
select 1 ID
union select 2
union select 3) A
select * into #T2 from(
select 1 ID
union select 2
union select 3) A
select * into #T3 from(
select 1 ID, 'ABC' Address, getDate() dateModified
union select 1, 'DEF', getDate()
union select 3, 'GHI', getDate()) A
select *, (select top 1 Address from #T3 T3 where T3.ID= T1.ID order by datemodified desc) from #T1 T1
inner join #T2 T2 on T1.ID = T2.ID
Bonus :- you can also add order by dateModified desc to get the latest address

how to replace a column of data with another column from another table?

I have two tables, tbl1(col1, col2, col3), tbl2(col1). I need to replace the data of tbl1.col1 with the data from tbl2.col1. My problem is there is no common field to join the two tables. Is it possible to write a query to do the update?
This should work. I'm not really sure what kind of data you have where there's no way to link Table2 and Table1, though:
WITH T1 AS
(
SELECT
RN = ROW_NUMBER() OVER (ORDER BY NULL)
,Col1
FROM
Tbl1
)
,T2 AS
(
SELECT
RN = ROW_NUMBER() OVER (ORDER BY NULL)
,Col1
FROM
Tbl2
)
UPDATE
T1
SET
Col1 = T2.col1
FROM
T1
INNER JOIN
T2
ON T1.RN = T2.RN