返回具有完全相同员工的所有组

时间:2012-07-09 21:59:34

标签: sql sql-server sql-server-2005

有2个表:

Employee
(id_employee, worker_name)

Groups
(id_employee, group_name)

以下是您的创作脚本:

CREATE TABLE Employee (
   id_employee int identity(1,1) NOT NULL CONSTRAINT PK_Employee PRIMARY KEY CLUSTERED,
   worker_name nvarchar(100) CONSTRAINT UQ_Employee_worker_name UNIQUE
);

CREATE TABLE Groups (
   id_employee int NOT NULL CONSTRAINT FK_Groups_id_employee FOREIGN KEY REFERENCES Employee (id_employee),
   group_name varchar(10) NOT NULL,
   CONSTRAINT PK_Groups PRIMARY KEY CLUSTERED (group_name, id_employee)
);

INSERT Employee
SELECT 'worker 1'
UNION ALL SELECT 'worker 2'
UNION ALL SELECT 'worker 3'
UNION ALL SELECT 'worker 4';

INSERT Groups
SELECT 1, 'a1'
UNION ALL SELECT 2, 'a1'
UNION ALL SELECT 3, 'a2'
UNION ALL SELECT 4, 'a2'
UNION ALL SELECT 1, 'b1'
UNION ALL SELECT 2, 'b1'
UNION ALL SELECT 3, 'b2'
UNION ALL SELECT 4, 'b2'
UNION ALL SELECT 2, 'b3'
UNION ALL SELECT 3, 'b3'
UNION ALL SELECT 4, 'b3';

我需要一个查询,对于给定的id_group,它将返回所有其他具有完全相同员工的组。

例如:

SELECT for 'a1'

- >应该返回'b1',因为在这两个组中都有:worker 1&工人2

SELECT for 'a2'

- >应该返回'b2',因为在这两个组中都有:worker 3&工人4

请注意,群组必须完全相同,a1的所有成员都必须位于b1中,并且两个群组的大小也必须相同。

5 个答案:

答案 0 :(得分:2)

您可以使用SQL set操作来完成工作。我们的想法是在组内将员工匹配在一起,并计算组中的总数。

select others.group_name
from (select g.*, count(*) over (partition by group_name) as numemps
      from groups g
      where group_name <> @group
     ) others left outer join
     (select g.*, count(*) over (partition by group_name) as numemps
      from groups g
      where group_name = @group
     ) thegroup
     on others.id_employee = thegroup.id_employee and
        others.numemps = thegroup.numemps
group by others.group_name
having count(*) = max(thegroup.numemps) and
       max(case when thegroup.id_employee is null then 1 else 0 end) = 0

因此,此查询将世界划分为两个。 。 。你的小组和所有其他小组。然后它按名称匹配它们并按组聚合。唯一的候选人群是雇员人数相同的人。

having子句选择匹配的组。这意味着另一个组中的每个名称都与您关注的组中的名称相匹配。由于组的大小相同,并且组中的每个名称都匹配,因此组包含相同的员工。

答案 1 :(得分:1)

您可以尝试此解决方案:

SELECT b.group_name
FROM
(
    SELECT aa.id_employee, aa.group_name, bb.group_count
    FROM groups aa
    CROSS JOIN
    (
        SELECT COUNT(1) AS group_count FROM groups WHERE group_name = 'a1'  
    ) bb
    WHERE aa.group_name = 'a1'
) a
INNER JOIN groups b ON a.id_employee = b.id_employee AND a.group_name <> b.group_name
INNER JOIN
(
    SELECT group_name, COUNT(1) AS other_group_count
    FROM groups
    GROUP BY group_name
) c ON b.group_name = c.group_name
WHERE a.group_count = c.other_group_count
GROUP BY b.group_name, a.group_count
HAVING COUNT(1) = a.group_count

答案 2 :(得分:0)

需要一些编辑来获得我想要的那个

with pairs as (
    select gs1.group_name as group1, gs2.group_name as group2, gs1.emp_count as emp_count
    from
    (select group_name, count(1) as emp_count from groups group by group_name) as gs1 inner join
    (select group_name, count(1) as emp_count from groups group by group_name) as gs2
        /* choose parameterized */
        --on gs1.group_name = 'a1' and gs1.group_name != gs2.group_name and gs1.emp_count = gs2.emp_count
        /* or all pairs */
        on gs1.group_name < gs2.group_name and gs1.emp_count = gs2.emp_count
)
select
    pairs.group1, pairs.group2
from
    pairs inner join

    (select group_name, id_employee from Groups) as g1
        on g1.group_name = pairs.group1 inner join

    (select group_name, id_employee from Groups) as g2
        on g2.group_name = pairs.group2 and g1.id_employee = g2.id_employee
group by
    pairs.group1, pairs.group2
having
    min(pairs.emp_count) = count(g1.group_name);

答案 3 :(得分:0)

这很有效。如果您想尝试,请参阅我在问题中添加的设置脚本。

SELECT DISTINCT G.group_name
FROM Groups G
WHERE
   G.group_name <> @group
   AND NOT EXISTS (
      SELECT *
      FROM
         (SELECT * FROM Groups WHERE group_name = @group) G1
         FULL JOIN (SELECT * FROM Groups WHERE G.group_name = group_name) G2
            ON G1.id_employee = G2.id_employee
      WHERE EXISTS (SELECT G1.id_employee EXCEPT SELECT G2.id_employee)
   );

答案 4 :(得分:0)

这是获取所需结果的SQL查询。

DECLARE @group_name varchar(10)='a1'
;WITH CTE(group_name,emp_ids) as (select group_name,(SELECT  cast(id_employee as varchar(10))+ ', ' as [text()]
    FROM    Groups where group_name=g.group_name 
    ORDER BY id_employee DESC
    FOR XML PATH('') )  as emp_ids from Groups g group by group_name)

SELECT group_name FROM CTE where emp_ids in(select emp_ids from CTE where group_name = @group_name)
and group_name <> @group_name