2

有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' 因为在这两个组中都有:工人 1 和工人 2

SELECT for 'a2'

-> 应该返回“b2”,因为在这两个组中都有:工人 3 和工人 4

请注意,组需要完全相同,所有成员都a1需要在其中,b1并且两个组的大小也需要相同。

4

5 回答 5

2

您可以使用 SQL 集合操作来完成这项工作。这个想法是在组内将员工匹配在一起并计算组中的总数。

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 子句选择匹配的组。这意味着其他组中的每个名称都与您关心的组中的名称匹配。由于组的大小相同,并且组中的每个名称都匹配,因此这些组包含相同的员工。

于 2012-07-09T22:54:49.623 回答
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
于 2012-07-09T22:09:01.797 回答
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)
   );
于 2012-07-09T23:51:51.227 回答
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 
于 2012-07-10T13:07:18.037 回答
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);
于 2012-07-09T23:03:45.587 回答