一尘不染

使用 WHERE CASE 的子查询返回超过 1 个值

sql

我有 3 个代表对象的相关表:客户、用户和潜在客户。用户具有“用户”或“管理员”类型,可以创建潜在客户并为客户提供服务。在模式术语中,多对一关系中的Users.Client引用和多对一关系中的引用。示例架构:Clients.Id``Leads.CreatedBy``Users.Username

CREATE TABLE Clients (
  Id INT IDENTITY PRIMARY KEY,
  Name VARCHAR(32) NOT NULL
);

CREATE TABLE Users (
  Id INT,
  Username VARCHAR(32) NOT NULL,
  Type VARCHAR(8) NOT NULL CHECK (Type IN ('Admin', 'User')),
  Client INT NOT NULL,
  PRIMARY KEY (Username),
  UNIQUE (id),
  FOREIGN KEY (Client) REFERENCES Clients (Id)
);

CREATE TABLE Leads (
  Id INT IDENTITY PRIMARY KEY,
  Name VARCHAR(64),
  Company VARCHAR(64),
  Profession VARCHAR(64),
  CreatedBy VARCHAR(32) NOT NULL,
  FOREIGN KEY (CreatedBy) REFERENCES Users (Username)
);

我正在编写一个查询来向用户展示他们的潜在客户。“用户”类型的用户应该只能查看他们创建的潜在客户。“管理员”类型的用户应该能够看到他们客户的所有潜在客户(但不能看到其他客户)。什么查询会Leads根据这些限制从表中获取行?我检查了其他问答,但我不知道如何将它们应用于上述情况。

我尝试了以下方法:

SELECT * 
  FROM Leads 
  WHERE createdby IN (
    CASE 
      WHEN (SELECT type 
              FROM users 
              WHERE username='Sathar'
           )='Admin' 
        THEN (
          SELECT username 
            FROM users 
            WHERE client=(
              SELECT client 
                FROM users 
                WHERE username='Sathar'
        )   )
      ELSE 'Sathar'
    END
  )

但是,它会产生错误:

子查询返回超过 1 个值。当子查询跟随 =、!=、<、<=、>、>= 或子查询用作表达式时,这是不允许的。

为了完善该示例,一些示例数据:

SET IDENTITY_INSERT Clients ON;

INSERT INTO Clients (Id, Name)
  VALUES
(1, 'IDM'),
(2, 'FooCo')
;

SET IDENTITY_INSERT Clients OFF;

INSERT INTO Users (Id, Username, Type, Client)
  VALUES
(1, 'Sathar', 'Admin', 1),
(2, 'bafh', 'Admin', 1),
(3, 'fred', 'User', 1),
(4, 'bloggs', 'User', 1),
(5, 'jadmin', 'Admin', 2),
(6, 'juser', 'User', 2)
;


INSERT INTO Leads (Name, Company, Profession, CreatedBy)
  VALUES
('A. Person', 'team lead', 'A Co', 'Sathar'),
('A. Parrot', 'team mascot', 'B Co', 'Sathar'),

('Alice Adams', 'analyst', 'C Co', 'juser'),
('"Bob" Dobbs', 'Drilling Equipment Salesman', 'D Co', 'juser'),
('Carol Kent', 'consultant', 'E Co', 'juser'),

('John Q. Employee', 'employee', 'F Co', 'fred'),
('Jane Q. Employee', 'employee', 'G Co', 'fred'),

('Bob Howard', 'Detached Special Secretary', 'Capital Laundry Services', 'jadmin')
;

以上所有内容都可以作为一个活生生的例子

如果没有CASE表达式,查询不会产生错误,但不会遵循所有限制(为类型的用户返回客户端的所有潜在客户User):

SELECT * 
  FROM Leads 
  WHERE createdby IN (
    SELECT username 
      FROM users 
      WHERE client=(
        SELECT client 
          FROM users 
          WHERE username='fred'
      )
  ) 

这可以从另一个实例中显示的结果中看出。


阅读 98

收藏
2022-07-22

共1个答案

一尘不染

这应该作为一个if elsenot as a来完成case,你可以这样做:

if (SELECT type FROM users WHERE username='[the username]') = 'Admin'
begin
    --The records you allow for admin to see for example
    (SELECT * 
    FROM Leads where createdby in 
    (
        select username 
        from users where client=(select client from users where username='Sathar')
    ))
end
else
begin
    --The records you allow for non admin to see for example
    (SELECT * 
    FROM Leads 
    WHERE createdby = 'Sathar')
end

或者真的’admin’应该用joins来完成,但同样的想法。

应该这样做的原因if else是因为case它是一个表达式而不是一个语句(就像在其他语言中一样switch case),while是一个条件语句,当你为每种类型的用户if else设置单独的 s 时,它会更好的设计,它会帮助你select不要制造错误。

2022-07-22