9

私が覚えていない適切な言葉があると確信していますが、問題を説明するのは簡単です: グループとメンバー間の単純な関係であるテーブル groupmembers があります:

id | groupid | memberid
1  | g1      | m1
2  | g1      | m2
3  | g2      | m1
4  | g2      | m2
5  | g2      | m3

上記では、m1 と m2 を含むグループと、m1、m2 および m3 を含むグループの 2 つのグループについて説明しています。メンバー m1、m2 を持ち、他のメンバーを持たないグループ ID を選択したい場合、どうすればよいですか? m1 と m2 はそれらのサブセットであるため、私が試したアプローチでも g2 が返されます。

更新: うわー、いくつかの素晴らしい答え! 最初に質問を少し明確にさせてください。指定されたメンバー m1 と m2 に正確に一致するグループを選択できるようにしたいと考えています。そのため、グループに m1 および m2 よりも多くのメンバーが含まれている場合は一致しないはずであり、グループに含まれるメンバーが m1 および m2 よりも少ない場合は一致しないはずです。

4

6 に答える 6

10

あなたの言葉から

メンバー m1、m2 を持ち、他のメンバーを持たないグループ ID を選択したい

これを試してみてください。背後にある考え方はcount、条件と句に一致するレコードのインスタンスの総数であり、whereグループごとのレコードの総数に等しいということです。

SELECT groupid
FROM table1 a
WHERE memberid IN ('m1','m2')
GROUP BY groupid
HAVING COUNT(*) = 
(
  SELECT COUNT(*)
  FROM table1 b
  WHERE b.groupid = a.groupid
  GROUP BY b.groupID
)

SQLFiddle デモ

于 2012-10-08T06:14:38.493 に答える
4

m1とm2を持つグループと、正確に2つのメンバーを持つグループの間の共通部分を探しています。SQLにはそのための演算子があります。

select groupid
from group_table
where memberid in ('m1','m2')
group by groupid 
having count(distinct memberid) = 2
intersect
select groupid 
from group_table
group by groupid 
having count(distinct memberid) = 2

(Oracleを使用している場合は、intersectと呼ばれますminus

SQLFiddleのデモは次のとおりです。http://sqlfiddle.com/#!12 / df94d / 1

John Wooのソリューションは、パフォーマンスの点でより効率的である可能性があると思いますが。

于 2012-10-08T06:55:17.543 に答える
2

このクエリには問題があります

SELECT groupid
FROM table1 a
WHERE memberid IN ('m1','m2')
GROUP BY groupid
HAVING COUNT(*) = 
(
  SELECT COUNT(*)
  FROM table1 b
  WHERE b.groupid = a.groupid
  GROUP BY b.groupID
)

m1 のみまたは m2 のみのグループに一致します。そのために、別のカウントチェックを追加できます

SELECT groupid
FROM table1 a
WHERE memberid IN ('m1','m2')
GROUP BY groupid
HAVING COUNT(*) = 2 --since we already know we should have exactly two rows
AND COUNT(*) = 
(
  SELECT COUNT(*)
  FROM table1 b
  WHERE b.groupid = a.groupid
  GROUP BY b.groupID
)
于 2013-07-09T16:12:33.157 に答える
1
-- sample table for discussion
CREATE TABLE tbl
  (id int, groupid varchar(2), memberid varchar(2));
INSERT INTO tbl
  (id, groupid, memberid)
VALUES
    (6, 'g4', 'm1'),
    (7, 'g4', 'm2'),
    (8, 'g6', 'm1'),
    (9, 'g6', 'm3'),
    (1, 'g1', 'm1'),
    (2, 'g1', 'm2'),
    (3, 'g2', 'm1'),
    (4, 'g2', 'm2'),
    (5, 'g2', 'm3')
;

-- the query
select a.groupid, b.groupid peer
from (select groupid, count(*) member_count, min(memberid) x, max(memberid) y
      from tbl
      group by groupid) A
join
     (select groupid, count(*) member_count, min(memberid) x, max(memberid) y
      from tbl
      group by groupid) B
  on a.groupid<b.groupid and a.member_count=b.member_count and a.x=b.x and a.y=b.y
join tbl A1
  on A1.groupid = A.groupid
join tbl B1
  on B1.groupid = B.groupid and A1.memberid = B1.memberid
group by A.groupid, b.groupid, A.member_count
having count(1) = A.member_count;

-- the result
GROUPID PEER
g1  g4

上記はgroups、非常に最適な方法で、同業者にリストされる方法を示しています。グループをメンバー数に分解し、最小値と最大値を取得することにより、大規模なデータベースでうまく機能します。グループは直接結合を使用して迅速に切り捨てられ、残りの一致についてのみ、グループ ID A と B で結合された完全なテーブルが参照され、それらが同等のグループであるかどうかが最終的に判断されます。

3 つの類似グループ (101,103,104) がある場合、セットは 3 つの別個の行 (101,103)、(101,104)、(103,104) として表示されます。各ペアがピアリングを形成するため、そのようなクエリは、いずれかが既にわかっている場合に最適に使用されます。ピアを見つけたいグループ。このフィルターは、最初のサブクエリに適合します。

于 2012-10-08T06:58:00.797 に答える
1
SELECT DISTINCT                          -- if (groupid, memberid) is unique
                                         -- no need for the DISTINCT
    a.groupid
FROM 
    tableX AS a
  JOIN
    tableX AS b  
      ON b.groupid = a.groupid 
WHERE a.memberid = 'm1' 
  AND b.memberid = 'm2'
  AND NOT EXISTS
      ( SELECT *
        FROM tableX AS t
        WHERE t.groupid = a.groupid
          AND t.memberid NOT IN ('m1', 'm2') 
      ) ;
于 2012-10-08T07:02:39.743 に答える
0
id | groupid | memberid
1  | g1      | m1
2  | g1      | m2
3  | g2      | m1
4  | g2      | m2
5  | g2      | m3

select GRPID from arcv where GRPID in (
select GRPID from arcv  
group by GRPID  having count(1)=2) and memberid in ('m1','m2')
于 2014-03-20T12:11:26.183 に答える