views:

99

answers:

3

I have two tables, "name" and "address". I would like to list the last_name and joined address.street_address of all last_name in table "name" that occur more than once in table "name".

The two tables are joined on the column "name_id".

The desired output would appear like so:

213 | smith | 123 bluebird | 
14  | smith | 456 first ave |
718 | smith | 12 san antonia st. |
244 | jones | 78 third ave # 45 |
98  | jones | 18177 toronto place |

Note that if the last_name "abernathy" appears only once in table "name", then "abernathy" should not be included in the result.

This is what I came up with so far:

SELECT name.name_id, name.last_name, address.street_address, count(*)
FROM `name`
JOIN `address` ON name.name_id = address.name_id
GROUP BY `last_name`
HAVING count(*) > 1

However, this produces only one row per last name. I'd like all the last names listed. I know I am missing something simple. Any help is appreciated, thanks!

A: 
SELECT name.name_id, name.last_name, address.street_address, count(name.last_name) as last_name_count
FROM `name`
JOIN `address` ON name.name_id = address.name_id
HAVING last_name_count > 1
Jestep
This needs a GROUP BY clause, and doing so will cause it to only return one row per name.
Chris Newman
Unless I'm missing something in the question, he specifically stated he only wants records with more than one last name listed. By using GROUP BY, the last name is limited to a single result.
Jestep
Your statement as it stands is invalid as there is no GROUP BY for the COUNT() to aggregate.OP wants to return every row that contains a last_name that appears more than once, not just a list of (distinct) last names that appear more than once. Looking at it another way, he wants the whole data set _except_ those with a unique last name. Using a GROUP BY on the main query cannot achieve this.
Chris Newman
You can't use HAVING clause without a GROUP BY, much less COUNT...
OMG Ponies
Ugh, long day. That made no sense now that I look at it again...
Jestep
+1  A: 

You could use a subquery as below, or use the same idea to join to a derived table if you prefer.

SELECT name.name_id, name.last_name, address.street_address
FROM `name`
JOIN `address` ON name.name_id = address.name_id
WHERE name.name_id IN (
  SELECT GROUP_CONCAT(name.name_id)
  FROM `name`
  GROUP BY `last_name`
  HAVING count(*) > 1
)
ORDER BY `last_name`
Chris Newman
sorry, this still only produces one row per last name, even when several rows of that last name may be present in the "name" table. thanks though. Rexem got it right.
Stoob
I see why now. Have fixed it.
Chris Newman
+2  A: 

Use:

SELECT t.name_id,
       t.last_name,
       a.street_address
  FROM NAME t
  JOIN ADDRESS a ON a.name_id = t.name_id
  JOIN (SELECT n.last_name
          FROM NAME n
      GROUP BY n.last_name
        HAVING COUNT(*) > 1) nn ON nn.last_name = t.last_name
OMG Ponies
thank you this is very creative and works perfectly, I have never seen a query like this one. Nicely done.
Stoob