tags:

views:

19

answers:

3

I've got two tables:

User (id, name, etc)
UserRight (user_id, right_id)

I want to find the users who have rights 1, 2 and 3, but no users who only have one or two of these. Also, the number of rights will vary, so searches for (1,2,3) and (1,2,3,4,5,6,7) should work with much the same query.

Essentially:

SELECT *
FROM User
WHERE (
    SELECT right_id 
    FROM tblUserRight 
    WHERE user_id = id 
    ORDER BY user_id ASC
) = (1,2,3)

Is this possible in MySQL?

A: 

In correspondance with the errors in my answer pointed out, here a solution with count and a subquery:

SELECT *
FROM User
WHERE 3 = (
    SELECT Count(user_id)
    FROM tblUserRight 
    WHERE right_id IN (1,2,3)
    AND user_id = User.id
)

An optimizer may of course change this to Martin Smith's solution (i.e. by using a group by).

inflagranti
WHERE right_id IN (1,2,3) , give also users that have only one right id, he want right_id =1 and right_id=2 and right_id=3
Haim Evgi
That isn't what the 'ALL' keyword does anyway.
Martin Smith
@inflagranti - By the way I though the same thing when I first heard about 'ALL' but I'm struggling to think when you would ever actually need to use it. `expr > ALL ()` would be better written as `expr > SELECT(MAX) ...` etc.
Martin Smith
@Martin Smith: I don't think the problem in my first approach was a misunderstanding of ALL, but a misuse in that case. You are right though, that I do neither see any use of ALL, as it can be expressed differently. (In fact, I never ever had used ALL in my over 8 years of SQL programming, but for whatever reason I thought it was appropriate here...)
inflagranti
+3  A: 
SELECT u.id, u.name ...
FROM User u
JOIN UserRight r on u.id = r.user_id
WHERE right_id IN (1,2,3)
GROUP BY u.id, u.name ...
HAVING COUNT DISTINCT(right_id) = 3
Martin Smith
A: 

You can also do this using PIVOT, especially if you want a visual representation. I did this on SQL Server - you may be able to translate it.

Declare @User Table (id  Int, name Varchar (10))
Declare @UserRight Table (user_id Int, right_id Int)

Insert Into @User Values (1, 'Adam')
Insert Into @User Values (2, 'Bono')
Insert Into @User Values (3, 'Cher')

Insert Into @UserRight Values (1, 1)
Insert Into @UserRight Values (1, 2)
Insert Into @UserRight Values (1, 3)
--Insert Into @UserRight Values (2, 1)
Insert Into @UserRight Values (2, 2)
Insert Into @UserRight Values (2, 3)
Insert Into @UserRight Values (3, 1)
Insert Into @UserRight Values (3, 2)
--Insert Into @UserRight Values (3, 3)


SELECT *
FROM @User U
    INNER JOIN @UserRight UR
        ON U.id = UR.User_Id
PIVOT
(
    SUM (User_Id)
    FOR Right_Id IN ([1], [2], [3])
) as xx
WHERE 1=1


SELECT *
FROM @User U
    INNER JOIN @UserRight UR
        ON U.id = UR.User_Id
PIVOT
(
    SUM (User_Id)
    FOR Right_Id IN ([1], [2], [3])
) as xx
WHERE 1=1
AND [1] IS NOT NULL
AND [2] IS NOT NULL
AND [3] IS NOT NULL
Raj More