tags:

views:

47

answers:

4

There are 3 tables in a database:

Users (UserID, UserName), Roles(RoleID, RoleName) and UserRoles(UserID, RoleID)

How to create a view on Users table which will have IsAdmin column, here is a mockup:

CREATE VIEW UsersView AS
    SELECT
        u.UserID,
        u.UserName,
        CASE WHEN ur.RoleID IS NULL THEN (0) ELSE (1) END AS IsAdmin
    FROM Users AS u
        LEFT JOIN Roles AS r ON r.RoleName = N'Admins'
        LEFT JOIN UserRoles AS ur ON  ur.UserID = u.UserID
                                  AND ur.RoleID = r.RoleID

IsAdmin should be (1) if user is in "Admins" user role and (0) if he is not

+1  A: 

try this

Here is another way...but I do like the EXISTS version that Charles Bretana posted better

CREATE VIEW UsersView AS
SELECT UserID,UserName, MAX(IsAdmin) as IsAdmin
FROM(SELECT
    u.UserID,
    u.UserName,
    CASE r.RoleName when 'Admins' then 1 else 0 end AS IsAdmin
FROM Users AS u
    LEFT JOIN UserRoles AS ur ON ur.UserID = u.UserID
    LEFT JOIN Roles r on ur.RoleID = r.RoleID) x
    GROUP BY UserID,UserName
SQLMenace
I thought they wanted to flatten the result.
ChaosPandion
Will it work if there are multiple roles attaches to the same user?
Grief Coder
where do you see that? All it says is "IsAdmin should be (1) if user is in "Admins" user role and (0) if he is not"
SQLMenace
I see what you are saying...I will update
SQLMenace
+1: Most scalable option if the OP wants to add support for other roles.
OMG Ponies
In a real Users table there are lots of other columns other than UserID, UserName.. grouping by all of them would look suspicious at least and might be not efficient.
Grief Coder
The derived table/inline view is over complicated - it could be done within the original query.
OMG Ponies
Interesting, according to the execution plans, our answers are nearly equivalent and beat out @Charles answer by a small amount. How this would work in the real world remains to be seen.
ChaosPandion
+1  A: 

try:

  CREATE VIEW UsersView AS 
    SELECT 
        u.UserID, 
        u.UserName, 
        Case When Exists
           (Select * from userRoles ur
                Join Roles r On r.RoleId = ur.Roleid
            Where ur.userId = u.UserId
               And r.RoleName = '"Admins') 
          Then 1 Else 0 End IsAdmin 
    FROM Users u 
Charles Bretana
Will this work efficiently? Wouldn't it be better to avoid using nested SELECT statement inside a VIEW?
Grief Coder
Well, I would seldom count on one syntactical version of a query to operate more or less efficiently than another. The Query Processor / Optimizer has wide latitude in how it actually executes the thing anyway, and most of the various options it has are determined more from indices and statistics than from how you constructed the SQL. As long as the sql is logically consistent, pick tjhe one that most clearly expresses your intent.
Charles Bretana
A: 

Add another column to your Roles table, isAdmin, and set it to true only for the Admin role. Then, in views and such, check for the isAdmin marker in the where clause.

Beth
+1  A: 

This approach worked. Take notice of how trivial it is to add new role checks.

Code

Declare @Users Table(UserID Int, UserName VarChar(256))
Declare @Roles Table(RoleID Int, RoleName VarChar(256))
Declare @UserRoles Table(UserID Int, RoleID Int)

Insert Into @Roles Select 1, 'Admins'
Insert Into @Roles Select 2, 'Role2'
Insert Into @Roles Select 3, 'Role3'
Insert Into @Roles Select 4, 'Genius'

Insert Into @Users Select 1, 'Phil'
Insert Into @UserRoles Select 1, 1
Insert Into @UserRoles Select 1, 2
Insert Into @UserRoles Select 1, 3
Insert Into @UserRoles Select 1, 4

Insert Into @Users Select 2, 'Jim'
Insert Into @UserRoles Select 2, 2
Insert Into @UserRoles Select 2, 3

Insert Into @Users Select 3, 'Susan'
Insert Into @UserRoles Select 3, 1
Insert Into @UserRoles Select 3, 2
Insert Into @UserRoles Select 3, 3


Select UserID,
       UserName,
       Cast([Admins] As Bit) As IsAdmin,
       Cast([Genius] As Bit) As IsGenius
From (
    Select  Users.UserID,
            Users.UserName,
            Roles.RoleName
    From @Users As Users
        Left Join @UserRoles As UserRoles On UserRoles.UserID = Users.UserID
        Left Join @Roles As Roles On UserRoles.RoleID = Roles.RoleID
) As Data
Pivot (
    Count(RoleName) For RoleName In (
        [Admins], [Genius]
    )
) As Result

Result

UserID  UserName IsAdmin IsGenius
2       Jim      0       0
1       Phil     1       1
3       Susan    1       0
ChaosPandion