0

グループ、メンバーシップ、人物、属性の 4 つのテーブルがあります。

グループ

GroupID
GroupName
ParentGroupID

メンバーシップ

PersonID
GroupID

PersonID
Name

属性

AttributeID
GroupID
Value

属性はグループに割り当てられ、グループにはメンバーシップ テーブルを介して人が割り当てられます。

特定の人に関連するすべての属性を表示したいと思います。

親のいないグループの誰かに対してこれを行うのに問題はありませんが、一部のグループは 2 または 3 レベルの深さでネストされています。CTE アプローチを使用しようとする私の試みは、これまでのところ何の結果も得ていません。

例の結果

Person.Name Membership.GroupID  Group.GroupID  Group.ParentGroupID  Attribute.Value
Fred        3                   1              NULL                 'Attribute for Top level group'
Fred        3                   2              1                    'Attribute for a sub group'
Fred        3                   3              2                    'Attribute for third sub group'
Fred        5                   4              1                    'Attribute for Top level group - this is a duplicate?'
Fred        5                   5              4                    'Attribute for second sub group'

それが十分に明確であることを願っています。Fred はグループ 3 のメンバーであり、2 の親グループがあり、さらに 3 の親グループがあります。次に、各グループに一致する各属性を表示します (Attribute.GroupID に対する Group.ID の内部結合がこれを実現します)。 )

編集 - メモを追加するだけで、各人物は複数のグループのメンバーになることができます。

4

1 に答える 1

2

DDL + DML

create table groups (groupid int, groupname varchar(10), parentgroupid int)
insert groups select 1, 'A', null;
insert groups select 2, 'B', null;
insert groups select 3, 'C', 1;
insert groups select 4, 'D', null;
insert groups select 5, 'E', null;
create table membership (personid int, groupid int);
insert membership select 1, 3;
insert membership select 1, 4;
create table person (personid int, name varchar(100));
insert person select 1, 'Jim';
create table Attribute(AttributeID int, GroupID int, Value varchar(100));
insert Attribute select 1, 1, 'At1-1';
insert Attribute select 2, 1, 'At1-2';
insert Attribute select 3, 2, 'At2-1';
insert Attribute select 4, 3, 'At3-1';
insert Attribute select 5, 4, 'At4-1';

クエリ

;with tmp as (
    select groupid membership_groupid, groupid
    from membership
    where personid = 1
    union all
    select membership_groupid, g.parentgroupid
    from groups g
    join tmp on tmp.groupid = g.groupid
)
select p.name, membership_groupid, g.groupid, g.parentgroupid, a.value
from person p
join tmp t on 1=1
join groups g on g.groupid = t.groupid
join attribute a on a.groupid = t.groupid
where p.personid = 1

また、個人が GROUP A と GROUP A の親の両方のメンバーになる可能性がある場合は、属性を 1 回だけ表示するように関係を解消する必要があります。

;with tmp as (
    select groupid membership_groupid, groupid
    from membership
    where personid = 1
    union all
    select membership_groupid, g.parentgroupid
    from groups g
    join tmp on tmp.groupid = g.groupid
)
select p.name, membership_groupid, g.groupid, g.parentgroupid, a.value
from person p
join (select *, rn=row_number() over (partition by groupid
                                      order by case when membership_groupid=groupid then 1
                                                    else 2 end,
                                               membership_groupid)
      from tmp) t on t.rn=1
join groups g on g.groupid = t.groupid
join attribute a on a.groupid = t.groupid
where p.personid = 1
于 2012-10-25T00:31:33.560 に答える