tags:

views:

130

answers:

3

Consider a MYSQL table called "comments" with 2 fields, "hostname" and "username".

How do I return a list sorted by hostname where the 2nd column is a list of usernames associated with each hostname? I can see how to do this with a scripting language like py, but is it possible as a standard sql qurey?

If I do "SELECT hostname,count(distinct(username)) FROM comments GROUP BY hostname" I get almost the right result, except It only gives me the number of usernames associated with each hostname instead of the actual list of usernames associated with each hostname... trying distinct(username) without the count() around it returns a syntax error.

+2  A: 

I think the cleanest way to do this is to just select distinct rows and reformat it in the client if necessary:

SELECT DISTINCT hostname, username
FROM comments
ORDER BY hostname, username

Alternatively if you want the results concatenated you can use GROUP_CONCAT:

SELECT hostname, GROUP_CONCAT(DISTINCT username) as usernames
FROM comments
GROUP BY hostname
Mark Byers
cool, I didn't know GROUP_CONCAT! How can you "turn it on"?
Balint Pato
Comment Deleted... you folks are very fast. Thanks, I am trying the suggestions.
Justin Keogh
+1 @Justin: do a better test, GROUP_CONCAT (http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat) will definitively return all usernames associated with a hostname.
Unreason
Yes, that did it (the GROUP_CONCAT) awesome. I didnt try the oracle tested code above, but thanks for that too.
Justin Keogh
group_concat is indeed what you need. this function limits it's results to a number of 1024 characters by default. If you need more, you can set group_concat_max_len variable to a higher value. http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_group_concat_max_lenalso if you need a different separator, you can do `GROUP_CONCAT(DISTINCT username separator ', ') `
ceteras
+1  A: 

You have to add a new user-defined aggregate function, which concatenates the collected username strings.

I would give a shot at this: http://www.codeproject.com/KB/database/mygroupconcat.aspx

Balint Pato
A: 
SELECT HOSTNAME,
      RTRIM(
          REPLACE(
              REPLACE(XMLAGG(XMLELEMENT("x", USERNAME)).getstringval(), '<x>', NULL),
              '</x>',
              ','
          ),
          ','
      ) LIST_OF_USERNAMES
FROM COMMENTS
GROUP BY HOSTNAME;

Example:

If the source table is:

HOSTNAME     USERNAME
10.12.110.80 GOOFY
10.12.110.80 MINNIE
10.12.110.81 STAR
10.12.110.81 MOON
10.12.110.81 SUN
10.12.110.82 MARMELADE
10.12.110.82 ORANGE
10.12.110.82 JUICE
10.12.110.82 LEMON

the output will be the following:

HOSTNAME     LIST_OF_USERNAMES
10.12.110.80 GOOFY,MINNIE
10.12.110.81 STAR,MOON,SUN
10.12.110.82 MARMELADE,ORANGE,JUICE,LEMON

It works fine in Oracle 10G R2.

The chicken in the kitchen
The solution is requested for mysql (searching for XMLAGG in http://dev.mysql.com/doc/refman/5.1/en/ yields no results; mysql has GROUP_CONCAT which does exactly what is requested in an efficient manner)
Unreason
You are right, the solution is requested ONLY for MYSQL, but I have thought that it would have been interesting posting the Oracle 10G R2 solution ;-)
The chicken in the kitchen
Not that interesting for people who don't need or use Oracle (read: almost anyone). I could probably find a cuneiform limerick if i felt like it, but who'd even be able to decipher it, much less care?
cHao