views:

54

answers:

2

I have tables like:

'profile_values'
userID | fid     | value  
-------+---------+-------
1      | 3       | [email protected]
1      | 45      | 203-234-2345
3      | 3       | [email protected]
1      | 45      | 123-456-7890

And:

'users'
userID | name       
-------+-------
1      | joe      
2      | jane     
3      | jake    

I want to join them and have one row with two of the values like:

'profile_values'
userID | name  | email          | phone
-------+-------+----------------+--------------
1      | joe   | [email protected]  | 203-234-2345
2      | jane  | [email protected] | 123-456-7890

I have solved it but it feels clumsy and I want to know if there is a better way to do it. Meaning solutions that are either more readable or faster(optimized) or simply best-practice.

Current solution: multiple tables selected, many conditional statements:

SELECT u.userID AS memberid,
       u.name AS first_name, 
       pv1.value AS fname,
       pv2.value as lname
FROM  users AS u,
      profile_values AS pv1, 
      profile_values AS pv2,
WHERE u.userID = pv1.userID
  AND pv1.fid = 3
  AND u.userID = pv2.userID
  AND pv2.fid = 45;

Thanks for the help!

+3  A: 

It's a typical pivot query:

  SELECT u.userid,
         u.name,
         MAX(CASE WHEN pv.fid = 3 THEN pv.value ELSE NULL END) AS email,
         MAX(CASE WHEN pv.fid = 45 THEN pv.value ELSE NULL END) AS phone,
    FROM USERS u
    JOIN PROFILE_VALUES pv ON pv.userid = u.userid
GROUP BY u.userid, u.name

Add "LEFT" before the "JOIN" if you want to see users who don't have any entries in the PROFILE_VALUES table.

OMG Ponies
This only returned me one row, when my users table in reality is 442 tuples big. Maybe I'm doing something wrong... Actually it is only giving me the first row in my users table paired with the values in my profile_values table
WmasterJ
@WmasterJ: Do the 441 other users have entries in the `PROFILE_VALUES` table? I'm willing to bet they don't - see my note about using a LEFT JOIN in that case.
OMG Ponies
@Ponies: Thanks for replying so fast. Yes they do have entries. In my other SQL that I run which is included in my question I actually only get something like 220 rows because those are the only one that have the values I'm looking for. I saw the LEFT JOIN comment, didn't work. My sql statement is a little different since I used an example here. But if you can find anything wrong in this SQL: http://piratepad.net/Io1HDPFHJi
WmasterJ
@WmasterJ: Ah, you need to specify the GROUP BY clause - it needs to contain all the column names that do **not** have an aggregate function (IE: MAX) performed on them.
OMG Ponies
ALL the columns? So i need to include all the other columns: e_add, e_mod, e_del, e_html, e_app, is_admin, lang, timezone_scheduleit, institution, logon_name....from my 'users' table??
WmasterJ
It does ring a bell. But when I use something like COUNT() then I only need to group on one other value not all the others. But with MAX() i need to include them all just so they aren't trunkated?
WmasterJ
@WmasterJ: MySQL supports non-standard behavior, allowing you to omit columns from the group by. For more info: http://dev.mysql.com/doc/refman/4.1/en/group-by-hidden-columns.html. In the future, don't simplify details for your questions too much.
OMG Ponies
@OMG Ponies: Thanks for the help :)
WmasterJ
A: 

I didn't say this, which I should have (@OMG Ponies) but I wanted to use this within a MySQL view. And for views to be editable you're not allowed to use aggregate functions and other constraints. So what I had to do whas use the same SQL query as I had described in the initial question.

Hope this helps someone, adding tag for creating views.

WmasterJ