Sql 在一对多表中查找重复项

Sql 在一对多表中查找重复项,sql,sql-server,Sql,Sql Server,我有一张非常简单的桌子: create table #Person_Tasks( Person_ID int, Task_ID int) 我喜欢找到所有从事同样工作的人。例如,P1在T1和T2上工作。我怎样才能找到其他所有只在T1和T2上工作的人 以下是一些示例数据: insert into #Person_Tasks values (0,0), (0,1), (0,2), (1,0), (1,1), (1,3), (2,0), (2,1), (2,2) 在本例中,只有P0和P2具有完全相同

我有一张非常简单的桌子:

create table #Person_Tasks( Person_ID int, Task_ID int)
我喜欢找到所有从事同样工作的人。例如,P1在T1和T2上工作。我怎样才能找到其他所有只在T1和T2上工作的人

以下是一些示例数据:

insert into #Person_Tasks
values
(0,0),
(0,1),
(0,2),
(1,0),
(1,1),
(1,3),
(2,0),
(2,1),
(2,2)
在本例中,只有P0和P2具有完全相同的任务。P1具有相同数量的任务,但一个任务与其他人的任务ID不匹配


这个表相当大,有1000人和100K任务。

这里有一种方法,假设行是唯一的:

with pt as (
      select pt.*, count(*) over (partition by person_id) as num_tasks
      from person_tasks pt
     )
select pt.person_id, pt2.person_id
from pt left join
     pt pt2
     on pt2.task_id = pt.task_id and pt.person_id <> pt2.person_id
group by pt.person_id, pt2.person_id, pt.num_tasks, pt2.num_tasks
having (count(*) = pt.num_tasks and pt.num_tasks = pt2.num_tasks) or
       pt2.person_id is null
这将执行自联接,然后统计每对的匹配数。如果所有计数都匹配,则这两个人的任务相同


这里是一个显示它工作的方法。

这里有一个方法,假设行是唯一的:

with pt as (
      select pt.*, count(*) over (partition by person_id) as num_tasks
      from person_tasks pt
     )
select pt.person_id, pt2.person_id
from pt left join
     pt pt2
     on pt2.task_id = pt.task_id and pt.person_id <> pt2.person_id
group by pt.person_id, pt2.person_id, pt.num_tasks, pt2.num_tasks
having (count(*) = pt.num_tasks and pt.num_tasks = pt2.num_tasks) or
       pt2.person_id is null
这将执行自联接,然后统计每对的匹配数。如果所有计数都匹配,则这两个人的任务相同


这是一个演示它工作的示例。

根据您的示例,这也可以工作:

SELECT Person_ID
FROM (
    SELECT *,
    COUNT(Task_ID) OVER(PARTITION BY Person_ID) cnt
    FROM Person_Tasks
    WHERE 
        Task_ID IN(1,2)
) D 
WHERE 
    cnt > 1
GROUP BY Person_ID

根据您的样本,这也适用:

SELECT Person_ID
FROM (
    SELECT *,
    COUNT(Task_ID) OVER(PARTITION BY Person_ID) cnt
    FROM Person_Tasks
    WHERE 
        Task_ID IN(1,2)
) D 
WHERE 
    cnt > 1
GROUP BY Person_ID

你能说得更具体些吗?一个人可以完成多少任务?有多少重叠被认为是匹配的?一些可用的样本数据如何?您所问的是所谓的关系划分。这是一个解释各种形式的例子,你能更具体一点吗?一个人可以完成多少任务?有多少重叠被认为是匹配的?一些可用的样本数据如何?您所问的是所谓的关系划分。这是一个解释各种形式的例子,我认为有一些语法错误。它应该与pt as一起使用。为什么会有选择pt.*?pt存在吗?@chhenning。谢谢。还有一些更正:使用pt作为select pt.*,按person_id作为num_任务从person_任务pt选择pt.person_id,pt2.person_id从pt左侧加入pt pt2上的pt pt2.task_id=pt.task_id按pt.person_id分组,pt2.person_id具有count=pt.num_任务和pt.num_任务=pt2.num_任务;仍然存在一些错误:Msg 8121,级别16,状态1,第106行列“pt.num_tasks”在HAVING子句中无效,因为它未包含在聚合函数或GROUP BY子句中。Msg 8121,级别16,状态1,第106行列“pt.num_tasks”在HAVING子句中无效,因为它未包含在聚合函数或GROUP BY子句中。Msg 8121,级别16,状态1,第106行列“pt.num_tasks”在HAVING子句中无效,因为它不包含在聚合函数或GROUP BY子句中。@chhenning。现在答案中有一个经过测试和验证的版本。我认为有一些语法错误。它应该与pt as一起使用。为什么会有选择pt.*?pt存在吗?@chhenning。谢谢。还有一些更正:使用pt作为select pt.*,按person_id作为num_任务从person_任务pt选择pt.person_id,pt2.person_id从pt左侧加入pt pt2上的pt pt2.task_id=pt.task_id按pt.person_id分组,pt2.person_id具有count=pt.num_任务和pt.num_任务=pt2.num_任务;仍然存在一些错误:Msg 8121,级别16,状态1,第106行列“pt.num_tasks”在HAVING子句中无效,因为它未包含在聚合函数或GROUP BY子句中。Msg 8121,级别16,状态1,第106行列“pt.num_tasks”在HAVING子句中无效,因为它未包含在聚合函数或GROUP BY子句中。Msg 8121,级别16,状态1,第106行列“pt.num_tasks”在HAVING子句中无效,因为它不包含在聚合函数或GROUP BY子句中。@chhenning。现在答案中有一个经过测试和验证的版本。