views:

39

answers:

3

hi,

I have a litte problem with a mysql query.

I use 5 tables:

user_has_data (uid, dataid); users (uid, uname); user_in_group(uid, groupid, data); groups(groupid, data, packageid); packages(packageid, name)

all ids are PK. I want to build a sql query that finds a user, which belongs to a specified dataid, by its uname and checks if the user is in a group (relation in table user_in_group) belonging to a specified package (a group is assigned to one package). if so data from users, package and group should be fetched, otherwise only the user data should be fetched. Therefore I use left joins, so I can also get the users with no group:

SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid` 
FROM `user_has_data` AS `uac` 
INNER JOIN `users` AS `u` ON u.uid = uac.uid 
LEFT JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid 
LEFT JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2) 
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`

Unfortunately I get wrong results: I get groups that have a different packageid than stated in the join, if the user has another group assigned to him with a different packageid.

probably this is because the first left join has no restrictions to packageid and the second is a left join and so it has no restrictions on the result (packageid is NULL for all results, but should have values). If I change the second left join to a ordinary join, the group problem would be fixed but the query cant find users without group any more.

Any ideas how to fix this or even possible? thanks in advance!

A: 

Because you are limiting your search to a specific group packageid of '2', why not just make both of your LEFT JOIN INNER JOINS and then throw in ag.packageid = 2 in your WHERE clause?

Neil Konitzer
if both joins are INNER JOINs the query cannot find users without groups any more (but it should also find that kind of users)
max
A: 

Are you saying that you are actually seeing the value ag.packageid = 2 in your query results?

If not, I think you might try something like:

SELECT `uac`.`uid`, `u`.`uid`, `g`.`groupid`, `g`.`packageid` 
FROM `user_has_data` AS `uac` 
INNER JOIN `users` AS `u` ON u.uid = uac.uid 
LEFT JOIN (`user_in_group` AS `uig` 
  INNER JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2) )
 AS `g` ON uac.uid = g.uid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
PMV
At first sight this works as expected! Thanks a lot.
max
A: 
SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid` 
FROM `user_has_data` AS `uac` 
INNER JOIN `users` AS `u` ON u.uid = uac.uid 
LEFT OUTER JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid 
LEFT OUTER JOIN `groups` AS `ag` ON ag.groupid = uig.groupid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
AND (ag.packageid = 2 OR uig.uid IS NULL) 
GROUP BY `u`.`uid`

I know LEFT JOIN and LEFT OUTER JOIN mean the same thing, but I like to be explicit. With the condition in your join, I bet you were getting groups with different packages, but weren't getting the packages?

Andrew
THanks for your answer. Actually it improves the result, but it only gets the users where no group is present (if I implemented it correct)...
max
I didn't pay attention to the GROUP BY. What do you get when you remove it?
Andrew