多次搜索一列

时间:2013-11-18 13:46:26

标签: sql-server sql-server-2008

我正在使用SQL Server 2008.

这是我的查询输出:

Reg_Id  |  ITSkillName  
----------------------
  118   |  JAVASCRIPT
  371   |  PHP
  371   |  ANDROID
  6170  |  PHP

这里,Reg_Id是外键。我希望Reg_Id具有PHP和ANDROID技能。

所以我尝试了

SELECT * 
FROM dbo.ITSkill AS is2 
WHERE ITSkillName = 'PHP' AND ITSkillName = 'ANDROID'

但它返回0条记录。请帮我。谢谢。

5 个答案:

答案 0 :(得分:3)

您需要JOIN自己的表格才能获得所需的结果。

 SELECT A.Reg_Id
   FROM dbo.ITSkill A
   INNER JOIN dbo.ITSkill B ON A.Reg_Id = B.Reg_Id AND B.ITSkillName='PHP'
   WHERE A.ITSkillName='ANDROID'

如果您需要匹配任意数量的技能,但无法保证Reg_ID, ITSkillName是唯一的,您可以使用CTE稍微修改Damien_The_Unbeliever的答案,如下所示:

   ;WITH UniqueSkills AS (SELECT DISTINCT Reg_ID, ITSkillName FROM dbo.ITSkill)
   SELECT Reg_ID,COUNT(*) FROM UniqueSkills AS is2
   WHERE ITSkillName IN(select Skill from @SearchSkills)
   GROUP BY Reg_ID
   HAVING COUNT(*) = (select COUNT(*) from @SearchSkills)

答案 1 :(得分:3)

这是一个关系划分问题。如果同时列出的Reg_IDITSkillName列在此表中是唯一的,那么我们就可以这样做:

   SELECT Reg_ID,COUNT(*) FROM dbo.ITSkill AS is2
   WHERE ITSkillName IN('PHP','ANDROID')
   GROUP BY Reg_ID
   HAVING COUNT(*) = 2

这通常通过调整IN子句和预期计数来扩展到更多技能。

即。如果你有一个包含搜索技能的表值参数,你可以:

   SELECT Reg_ID,COUNT(*) FROM dbo.ITSkill AS is2
   WHERE ITSkillName IN(select Skill from @SearchSkills)
   GROUP BY Reg_ID
   HAVING COUNT(*) = (select COUNT(*) from @SearchSkills)

其中@SearchSkills是表值参数。

答案 2 :(得分:3)

成套思考!您正在寻找的是两组的交叉点:具有PHP技能的那些和具有ANDROID技能的那些。 SQL有一个INTERSECT运算符:

SELECT Reg_ID FROM dbo.ITSkill
WHERE Skill = 'PHP'

INTERSECT

SELECT Reg_ID FROM dbo.ITSkill
WHERE Skill = 'ANDROID'

答案 3 :(得分:2)

SELECT * FROM dbo.ITSkill AS is2 
WHERE ITSkillName = 'PHP' 
AND Reg_Id IN( SELECT DISTINCT Reg_Id 
                FROM dbo.ITSkill 
                WHERE ITSkillName = 'ANDROID')

<强>测试

DECLARE @t TABLE (Reg_Id INT,ITSkillName VARCHAR(20))
INSERT INTO @t
VALUES 
  (118,'JAVASCRIPT'),
  (371,'PHP'),
  (371,'ANDROID'),
  (6170,'PHP')


SELECT * FROM @t AS is2 
WHERE ITSkillName = 'PHP' 
AND Reg_Id IN( SELECT DISTINCT Reg_Id 
                FROM @t 
                WHERE ITSkillName = 'ANDROID')

结果集

Reg_Id  ITSkillName
371     PHP

答案 4 :(得分:0)

正如marc_s所说,INTERSECT是一个有效的选择。但是,由于查询优化器(至少在我的经验中)可能会选择执行查询的最佳方式,因此取决于有多少种技能,它可能会变得很重。

至少另一个选择是使用它:

SELECT s.*
FROM dbo.ITSkill s
JOIN 
   (SELECT Reg_ID
   FROM dbo.ITSkill AS is2 
   WHERE ITSkillName IN ('PHP','ANDROID')
   GROUP BY Reg_ID
   HAVING COUNT(DISTINCT ITSkillName) = 2) SRC
      ON SRC.Reg_ID = s.Reg_ID

现在显然,您需要更新HAVING COUNT值以匹配IN子句中的参数数量。在代码中,您有时可以连接数百个INTERSECT查询,这就是这个模型真正开始闪耀的地方。至少它应该在性能方面同样有效。

编辑:呸,刚刚注意到达米恩在那里有同样的想法!但是这也有加入以获得OP的结果所以我会留在这里。把信誉和财富交给达米恩。 ;)