查找仅在每个项目中提供Service2的承包商

时间:2013-05-21 00:20:55

标签: sql-server sql-server-2005

我有一张project表。每行都是项目的服务或产品。

Project  Contractor  Service
=======  ==========  =======
  1         B           S1
  1         A           S2
  1         A           S3
  1         C           S1
  2         D           S2
  2         A           S1
  2         B           S3
  3         E           S2
  3         B           S1
  3         C           S2

我想找到在项目中提供S2的承包商,并且没有在他们提供的同一项目上提供任何其他服务。

1  NULL
2  D
3  E
3  C

我在SQL中提取数据并进行过滤并将其分组到Excel中,但我想在SQL中找到一种方法。使用SQL Server 2005。

2 个答案:

答案 0 :(得分:2)

我会选择反半连接(NOT EXISTS语句):

SELECT AllS2.[Project],
    AllS2.[Contractor],
    AllS2.[Service]
FROM [StackoverflowProjects] AllS2
WHERE AllS2.[Service] = 'S2'
AND NOT EXISTS (SELECT NULL
    FROM StackoverflowProjects NonS2
    WHERE AllS2.Project = NonS2.Project 
    AND AllS2.Contractor = NonS2.Contractor 
    AND AllS2.Service <> 'S2')

如果您需要帮助解释,请告诉我。但它确实有效。

更新

首先让我指出,我将这些别名重命名为不那么抽象,希望更有帮助。

  

我想找到在项目上提供S2的承包商,并且没有在他们提供的同一个项目上提供任何其他服务。

我从这个声明中知道你想要的承包商只提供S2服务。如果您还不熟悉NOT部分,那么EXISTS部分可能会有点棘手。

因此,让我做相反的事情并解释它的作用:

SELECT AllS2.[Project],
    AllS2.[Contractor],
    AllS2.[Service]
FROM [StackoverflowProjects] AllS2
WHERE AllS2.[Service] = 'S2'
AND EXISTS (SELECT NULL
    FROM StackoverflowProjects NonS2
    WHERE AllS2.Project = NonS2.Project 
    AND AllS2.Contractor = NonS2.Contractor 
    AND AllS2.Service <> 'S2')

将向您展示所有承包商&#39;执行S2服务的项目以及S2以外的任何服务。

此外,这里有link to a blog article帮助我了解半连接(EXISTS)和反半连接(NOT EXISTS)在我第一次学习时的好处。< / p>

答案 1 :(得分:0)

;WITH ServiceCount AS (
    -- Contractor projects that have only one service
    SELECT Project, Contractor, COUNT(*) as [Count]
    FROM Projects
    GROUP BY Project, Contractor
    HAVING COUNT(*) = 1
)
SELECT
    sc.Project,
    sc.Contractor
FROM ServiceCount sc
JOIN Projects p
    ON p.Project = sc.Project
    AND p.Contractor = sc.Contractor
WHERE p.Service = 'S2'