如何选择此查询的大小写?

时间:2016-03-30 14:30:03

标签: sql-server if-statement inner-join select-case

SQL FIDDLE DEMO HERE

我有这种表结构:

    CREATE TABLE Users

            ([UserId] int, 
            [IdDepartment] int);

    INSERT INTO Users
        ([UserId], [IdDepartment])
    VALUES
        (1, 5),
        (2, 0),
        (3, -1),
        (4, 0),
        (5, -1),
        (6, 0);

    CREATE TABLE Department
        ([IdDepartment] int, [Name] varchar(23), [IdUser] int);

    INSERT INTO Department
        ([IdDepartment], [Name], [IdUser])
    VALUES
        (1, 'Sales', 3),
        (2, 'Finance', null ),
        (3, 'Accounting' , 5),
        (4, 'IT' ,3),
        (5, 'Secretary',null),
        (6, 'Sport',3);

我希望得到一个包含此结果的查询: 在Users表中,如果IdDepartment为0,则表示该用户是管理员,因此他可以看到所有部门。如果用户在idpartment中有-1,则意味着用户可以访问有限的部门,因此在这种情况下,我对Department表进行内部联接以获取这些部门的列表。最后一种情况是,如果用户在用户表中的idDepartament号码与0不同且不同于-1,则表示用户只能访问该部门。

我尝试做类似的事情,但结构不合理:

select
    case idDepartment
       when  0 then (select Name from Department)
       when -1 then (select Name from Department where IdUser = 3)
       else         (select Name from Department 
                      inner join Users on Department.idDepartment = Users.Department         
                      where Users.UserId = 3)
    end
from 
    Department
where 
    IdUser = 3

我该怎么做?感谢。

我为我想要的内容添加一个例子:

 -For the user that has the userid (1) -->

    Department Name
    ---------------
    Secretary




-For the user that has the userid (2) -->

    Department Name
    ---------------
    Sales
    Finance
    Accounting
    IT
    Secretary
    Sport




-For the user that has the userid (3) -->

    Department Name
    ---------------
    Sales
    IT
    Sports

4 个答案:

答案 0 :(得分:2)

你不能在SELECT CASE做类似的事情,最好的办法就是引入一些逻辑

DECLARE @IdUser INT = 3
DECLARE @userDepartment INT
SELECT @userDepartment = IdDepartment
FROM Users
WHERE UserId = @IdUser

IF @userDepartment = 0
BEGIN
    SELECT Name FROM Department
END
ELSE IF @userDepartment = -1
BEGIN
   SELECT Name FROM Department WHERE IdUser = @IdUser
END
ELSE
BEGIN
    SELECT Name FROM Department 
    INNER JOIN Users 
       ON Department.idDepartment = Users.IdDepartment 
    WHERE Users.UserId = @IdUser
END

顺便说一句,你已经找到了为什么你的结构不是理想。如果您在用户和用户之间有一个联结表。各部门,您可以使用更简单的查询来建模您已经拥有的任何组合(以联结表中的大量行为代价)

答案 1 :(得分:2)

您的示例代码有点令人困惑,但感觉您正在寻找类似的内容:

declare @id_user int = 3

select d.IdDepartment, d.Name
from Department d
where exists
  (
    select 1
    from Users u
    where u.[UserId] = @id_user
      and u.IdDepartment in (0, d.IdDepartment)
  )
  or d.[IdUser] = @id_user

实现:

  • 如果IdUser表中的Department与给定的@id_user相同 - 他肯定可以访问此部门
  • 否则,如果用户的IdDep值为0或等于相应的部门ID,则该用户可以访问部门

但是你的权限/安全模型闻起来并不好,而且它绝对不可扩展。您最好发明另一个实体(表)来存储允许的元组:(IdUser,IdDepartment)。在这种情况下,选择语句看起来会更清晰。

答案 2 :(得分:1)

  declare @IdUser int = 3;
  SELECT u.[UserId], d.Name 
  from Users u
  join Department d
        on   u.[IdDepartment] =  0 
        or ( u.[IdDepartment] = -1 and d.[IdUser]       = u.[UserId] )
        or ( u.[IdDepartment] >  0 and d.[IdDepartment] = u.[IdDepartment] )
   where u.[UserId] = @IdUser 
   order by u.[UserId], d.Name

userID 3应包含运动

答案 3 :(得分:-1)

如果我从你的伪查询中了解你正在尝试做什么,你可以使用精心构造的WHERE子句来做到这一点:

case idDepartment
   when 0 then (select Name from Department)
   when -1 then (select Name from Department where IdUser = 3)
   else (select Name from Department inner join Users on     Department.idDepartment = Users.Department where Users.UserId = 3)
end

可以写成子选择:

(SELECT Name
 FROM Department
 LEFT OUTER JOIN Users
   on     Department.idDepartment = Users.Department
 WHERE idDepartment=0
 OR (idDepartment = -1 AND idUser = 3)
 OR (Users.UserId = 3)
)

当然,您必须将子选择关联到外部查询。