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'

-> 両方のグループにワーカー 1 とワーカー 2 があるため、'b1' を返す必要があります。

SELECT for 'a2'

-> 両方のグループにワーカー 3 とワーカー 4 があるため、'b2' を返す必要があります。

グループはまったく同じである必要があり、すべてのメンバーが含まれている必要があり、両方のグループのサイズも同じである必要があることに注意して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

したがって、このクエリは世界を 2 つに分割します。. . あなたのグループと他のすべてのグループ。次に、それらを名前で照合し、グループ別に集計します。候補グループは、従業員数が同じグループのみです。

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

欲しいものを手に入れるのに少し編集が必要でした

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 に答える
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 に答える