在逗号分隔的列表中查找经理

Posted

技术标签:

【中文标题】在逗号分隔的列表中查找经理【英文标题】:Find manager in a comma-separated list 【发布时间】:2013-08-08 21:03:16 【问题描述】:

我有一个带有 ID 和责任经理的项目表。责任经理列的值为 John,Jim 用于项目 1,Jim,Julie 用于项目 2。

但如果我将 Jim 传递给我的存储过程,我应该得到 2 个项目 (1,2)。这不会返回任何行,因为该列是 John,Jim,但 SQL Server 正在寻找 ='Jim'

 select distinct ID,Manager from Projects where Manager=@Manager

【问题讨论】:

为什么要在单个列中存储以逗号分隔的经理姓名列表?标准化。请。 【参考方案1】:
WHERE ',' + Manager + ',' LIKE '%,Jim,%'

或者我想匹配你的实际代码:

WHERE ',' + Manager + ',' LIKE '%,' + @Manager + ',%'

请注意,您的设计存在极大缺陷。根本没有理由将名称存储在此表中,更不用说任何数据点的逗号分隔列表。这些事实本身就很重要,所以要这样对待它们!

CREATE TABLE dbo.Managers
(
  ManagerID INT PRIMARY KEY,
  Name NVARCHAR(64) NOT NULL UNIQUE, ...
);

CREATE TABLE dbo.Projects
(
  ProjectID INT PRIMARY KEY,
  Name NVARCHAR(64) NOT NULL UNIQUE, ...
);

CREATE TABLE dbo.ProjectManagers
(
  ProjectID INT NOT NULL FOREIGN KEY REFERENCES dbo.Projects(ProjectID),
  ManagerID INT NOT NULL FOREIGN KEY REFERENCES dbo.Managers(ManagerID)
);

现在设置您提到的示例数据:

INSERT dbo.Managers(ManagerID, Name)
  VALUES(1,N'John'),(2,N'Jim'),(3,N'Julie');

INSERT dbo.Projects(ProjectID, Name)
  VALUES(1,N'Project 1'),(2,N'Project 2');

INSERT dbo.ProjectManagers(ProjectID,ManagerID)
  VALUES(1,1),(1,2),(2,2),(2,3);

现在查找 Jim 管理的所有项目:

DECLARE @Manager NVARCHAR(32) = N'Jim';

SELECT p.ProjectID, p.Name
  FROM dbo.Projects AS p
  INNER JOIN dbo.ProjectManagers AS pm
  ON p.ProjectID = pm.ProjectID
  INNER JOIN dbo.Managers AS m
  ON pm.ManagerID = m.ManagerID
  WHERE m.name = @Manager;

或者你甚至可以手动短路一下:

DECLARE @Manager NVARCHAR(32) = N'Jim';


DECLARE @ManagerID INT;
SELECT @ManagerID = ManagerID
  FROM dbo.Managers
  WHERE Name = @Manager;

SELECT p.ProjectID, p.Name
  FROM dbo.Projects AS p
  INNER JOIN dbo.ProjectManagers AS pm
  ON p.ProjectID = pm.ProjectID
  WHERE pm.ManagerID = @ManagerID;

甚至更多:

DECLARE @Manager NVARCHAR(32) = N'Jim';


DECLARE @ManagerID INT;
SELECT @ManagerID = ManagerID
  FROM dbo.Managers
  WHERE Name = @Manager;

SELECT ProjectID, Name
  FROM dbo.Projects AS p
  WHERE EXISTS 
  (
    SELECT 1 
      FROM dbo.ProjectManagers AS pm
      WHERE pm.ProjectID = p.ProjectID
      AND pm.ManagerID = @ManagerID
  );

顺便说一句,我真的,真的,真的希望您原始查询中的DISTINCT 是不必要的。您真的有多个项目具有相同的名称​​和 ID?

【讨论】:

是的!必须区分吉姆和吉米!对于 SQL Server,CONTAINS() 会比 LIKE 快吗? @ebyrob 好吧,包含需要全文搜索,所以那里没有简单的答案。我的观点是,这些数据一开始就存储错误,不同的设计将确保您不必关心哪种类型的字符串搜索更快。 这里没有关于标准化的争论。我不认为你在我评论时添加了那部分...... @ebyrob 不,答案通常是在第一分钟内进行的工作。 :-)【参考方案2】:

WHERE 子句中,= 运算符查找完全匹配。您可以使用带有通配符的LIKE 进行部分匹配。

where Manager LIKE '%Jim%'

【讨论】:

除此之外还会找到 Jimbo 和 Bobby-Jim。【参考方案3】:

您可以尝试以下方法:

SELECT DISTINCT 
    ID,
    Manager 
FROM 
    Projects 
WHERE 
    (
     (Manager LIKE @Manager + ',*') OR
     (Manager LIKE '*,' + @Manager) OR
     (Manager  = @Manager) 
    )

这应该包括名字和姓氏,同时仍然搜索字面值。然而,性能可能是一个问题,具体取决于表

【讨论】:

* 在这里应该是通配符吗?这可能适用于 Access(或其他平台),但不适用于 SQL Server。此外,这还假设一个项目最多只有 2 名经理。【参考方案4】:

请尝试以下查询

select distinct ID,Manager from Projects where replace('#$#' + Manager + '#$#', ',', '#$#') like '%Jim%'

【讨论】:

以上是关于在逗号分隔的列表中查找经理的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用啥正则表达式在逗号分隔列表中查找 Nᵗʰ 条目?

Excel:查找所有匹配值并放在逗号分隔列表中?

以逗号分隔的字符串查找目录列表,不带尾随逗号

如何使用 LINQ 查找包含 2 个逗号分隔的字符串的匹配项

检查逗号分隔列表是不是包含特定数字[重复]

导出CSV文件是以逗号为分隔符的吗?