简体   繁体   中英

Regarding SQL Server query and joining

Basically I have 3 tables user , colors and usercolor .

Table structure:

  • User table has columns like UserID , UserName
  • Color table has columns like ColorID , ColorName
  • UserColor table has columns UserID , ColorID

When user login and go to my view first time then all color will be fetch and show in view with checkboxes as a result user can select any or many.

When any user select any color or many color from UI and save in db then userid and color id will be saved in user colors table but the same user again come to view then all colors will be show and if he previously selected anyone then those color name checkbox will be shown as checked.

I prepare a SQL statement to fetch all color data joining two table colors & usercolor , but the moment I specify userid then one records is fetching that is not right. I want to show always all distinct color name for every user and if user selected any then that color name show be shown by selected checkbox.

Here is my query:

SELECT        
    dbo.Colors.ColorID, dbo.Colors.ColorName, 
    ISNULL(dbo.UserColor.UserID, 0) AS IsSelected
FROM
    dbo.UserColor 
INNER JOIN
    dbo.Users ON dbo.UserColor.UserID = dbo.Users.UserID 
RIGHT OUTER JOIN
    dbo.Colors ON dbo.UserColor.ColorID = dbo.Colors.ColorID
WHERE        
   (dbo.Users.UserID = 1)

The above query return one data but I need to show all color names and one extra field like IsSelected which indicate which color user had selected previously. please help me to construct the SQL . Thanks

Pretty sure you are looking for something along these lines.

select c.ColorID
    , c.ColorName
    , IsSelected = case when uc.ColorID is null then 0 else 1 end
from dbo.Colors c
left join dbo.UserColor uc on uc.ColorID = c.ColorID and uc.UserID = 1 --leave this in the join or it becomes an inner join
left join dbo.Users u on u.UserID = uc.UserID

You may try this version with a subquery

DECLARE @userID as INT = NULL;

 SELECT uc.ColorID, uc.ColorName, max(uc.IsSelected) 
 FROM
 (
  SELECT 
        c.ColorID
        , c.ColorName
        , uc.UserID
        , IsSelected = case when uc.UserID = @userID then 1 else 0 end
    FROM dbo.Colors c
    LEFT JOIN dbo.UserColor uc on c.ColorID = uc.ColorID 
   ) uc
   WHERE uc.UserID = @userID OR uc.IsSelected = 0 
   GROUP BY uc.ColorID, uc.ColorName

in this way you get always all colors censed in dbo.Colors for the user you want selected based on previous saved choices.

You may try its working on rextester

Are you sure that you want a user to have many colors? Your structure allows a user to have that. You could simplify by moving ColorId to User table and skip UserColor table...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM