加入具有不同排名最高行的表

时间:2016-06-03 16:58:55

标签: sql sql-server distinct

我有三个像这样定义的表:

[tbMember]
memberID | memberName
1        | John
2        | Peter

[tbGroup] 
groupID | groupName
1       | Alpha
2       | Beta
3       | Gamma    

[tbMemberGroupRelation]
memberID | groupID | memberRank (larger number is higher)
1        | 1       | 0
1        | 2       | 1
2        | 1       | 5
2        | 2       | 3
2        | 3       | 1

现在我想执行一个表连接选择,以获得包含(不同)成员的结果,每个行中排名最高的组,对于上面给出的示例,查询结果需要:

memberID | memberName | groupName | memberRank
1        | John       | Beta      | 1
2        | Peter      | Alpha     | 5

有没有办法在单个SQL中实现它,如下面的样式?

select * from tbMember m
    left join tbMemberGroupRelation mg on (m.MemberID = mg.MemberID and ......)
    left join tbGroup g on (mg.GroupID = g.GroupID)

如果无法用简单的查询进行编写,也会感激任何其他解决方案。

  

=========更新=========

     

表格中只允许一个最高等级

3 个答案:

答案 0 :(得分:2)

一种解决方案是创建memberRank的反转序列/等级,以便每个成员的最高等级始终等于1.

这是我使用子查询实现它的方式:

SELECT
    m.memberID,
    m.memberName,
    g.groupName,
    mg.memberRank
FROM
    tbMember m
LEFT JOIN
    (
    SELECT
        memberID,
        groupID,
        groupName,
        memberRank,
        RANK() OVER(PARTITION BY memberID ORDER BY memberRank DESC) AS invRank
    FROM
        tbMemberGroupRelation
    ) mg
    ON (mg.memberID = m.memberID)
    AND (mg.invRank = 1)
LEFT JOIN
    tbGroup g
    ON (g.groupID = mg.groupID);

答案 1 :(得分:1)

create table [tbGroup] (groupid int, groupname varchar(8000))
Insert [tbGroup] Values (1, 'Alpha')
Insert [tbGroup] Values (2, 'Beta')
Insert [tbGroup] Values (3, 'Gamma')

create table [tbMemberGroupRelation] (memberid int, groupid int, memberrank int)
Insert [tbMemberGroupRelation] Values (1,1,0)
Insert [tbMemberGroupRelation] Values (1,2,1)
Insert [tbMemberGroupRelation] Values (2,1,5)
Insert [tbMemberGroupRelation] Values (2,2,3)
Insert [tbMemberGroupRelation] Values (2,3,1)

;With cteMemberGroupRelation As
(
Select *, Row_Number() Over (Partition By MemberID Order By MemberRank Desc) SortOrder
    From [tbMemberGroupRelation]
)
 Select *
    From tbMember M
    Join (Select * From cteMemberGroupRelation Where SortOrder = 1) R On R.memberid = M.memberid
    Join tbGroup G On G.groupid = R.groupid

答案 2 :(得分:1)

另一种方法:

SELECT
    M.memberID,
    M.memberName,
    G.groupName,
    MG.memberRank
FROM
    Member M
LEFT OUTER JOIN MemberGroup MG ON MG.memberID = M.memberID
LEFT OUTER JOIN MemberGroup MG2 ON
        MG2.memberID = M.memberID AND
        MG2.memberRank > MG.memberRank
INNER JOIN [Group] G ON G.groupid = MG.groupid
WHERE
    MG2.memberid IS NULL

由于索引等原因,在某些情况下可能会表现更好