Reputation: 91
I have a table that looks something like this:
first | last
John | Smith
Bob | dfgdf
John | fggf
John | Smith
And I want to run a query that will return only rows that have a unique last name for each first name. So only Bob dfgdf should be returned. Currently, I'm grouping twice and checking if count = 1, but is there a faster way?
SELECT first FROM (
SELECT first, last FROM table1 GROUP BY first, last
)as t1 GROUP BY first HAVING COUNT(*) = 1
Upvotes: 0
Views: 1654
Reputation: 1269463
I would do this as:
SELECT first
FROM table1
GROUP BY first
HAVING MIN(last) = MAX(last);
Actually, this should make use of an index on table1(first, last)
.
If the above doesn't use the index, then I would expect the fastest way to be:
select distinct on (first) first
from table1 t1
where not exists (select 1 from table1 tt1 where tt1.first = t1.first and tt1.last <> t1.last)
order by first;
This can make use of an index on table1(first, last)
for performance.
Upvotes: 1
Reputation: 520898
Try this version:
SELECT first
FROM table1
GROUP BY first
HAVING COUNT(*) = COUNT(DISTINCT last);
This just retains only first names whose record count is coincident with the count of distinct last names, which would imply that each first name maps to a distinct last name.
Edit:
If you want all columns from all matching rows, then you may try:
WITH cte AS (
SELECT first
FROM table1
GROUP BY first
HAVING COUNT(*) = COUNT(DISTINCT last)
)
SELECT t1.*
FROM table1 t1
INNER JOIN cte t2
ON t1.first = t2.first;
Upvotes: 1