92

I want to select rows that have a distinct email, see the example table below:

+----+---------+-------------------+-------------+
| id | title   | email             | commentname |
+----+---------+-------------------+-------------+
|  3 | test    | rob@hotmail.com   | rob         |
|  4 | i agree | rob@hotmail.com   | rob         |
|  5 | its ok  | rob@hotmail.com   | rob         |
|  6 | hey     | rob@hotmail.com   | rob         |
|  7 | nice!   | simon@hotmail.com | simon       |
|  8 | yeah    | john@hotmail.com  | john        |
+----+---------+-------------------+-------------+

The desired result would be:

+----+-------+-------------------+-------------+
| id | title | email             | commentname |
+----+-------+-------------------+-------------+
|  3 | test  | rob@hotmail.com   | rob         |
|  7 | nice! | simon@hotmail.com | simon       |
|  8 | yeah  | john@hotmail.com  | john        |
+----+-------+-------------------+-------------+

Where I don't care which id column value is returned. What would be the required SQL?

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Adam
  • 6,041
  • 36
  • 120
  • 208

5 Answers5

118

Quick one in TSQL

SELECT a.*
FROM emails a
INNER JOIN 
  (SELECT email,
    MIN(id) as id
  FROM emails 
  GROUP BY email 
) AS b
  ON a.email = b.email 
  AND a.id = b.id;
ypercubeᵀᴹ
  • 113,259
  • 19
  • 174
  • 235
Turbot
  • 5,095
  • 1
  • 22
  • 30
45

I'm assuming you mean that you don't care which row is used to obtain the title, id, and commentname values (you have "rob" for all of the rows, but I don't know if that is actually something that would be enforced or not in your data model). If so, then you can use windowing functions to return the first row for a given email address:

select
    id,
    title,
    email,
    commentname

from
(
select 
    *, 
    row_number() over (partition by email order by id) as RowNbr 

from YourTable
) source

where RowNbr = 1
Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • 2
    This is the best solution, because it can apply to duplicate rows that do not have a unique identity column, or ones that do. – Antony Booth Mar 16 '15 at 18:27
  • ....Yes this solved the issue for me....the solution above only grouped the table data together.....i.e for Microsoft SQL 2008 Server/data .........thanks Adam...... – Siwoku Adeola Jun 14 '16 at 06:28
  • This is a really good solution that works great for smaller tables. Is there a way to do this without having to list each column in the SELECT statement? – David Mar 04 '21 at 18:56
5

If you are using MySql 5.7 or later, according to these links (MySql Official, SO QA), we can select one record per group by with out the need of any aggregate functions.

So the query can be simplified to this.

select * from comments_table group by commentname;

Try out the query in action here

Community
  • 1
  • 1
RamValli
  • 4,389
  • 2
  • 33
  • 45
2

Since you don't care which id to return I stick with MAX id for each email to simplify SQL query, give it a try

;WITH ue(id)
 AS
 (
   SELECT MAX(id)
   FROM table
   GROUP BY email
 )
 SELECT * FROM table t
 INNER JOIN ue ON ue.id = t.id
sll
  • 61,540
  • 22
  • 104
  • 156
-2

SELECT * FROM emails GROUP BY email;

Deepak Raj
  • 19
  • 3