选择基于特定列的连接生成的多行之一

时间:2013-09-26 21:29:43

标签: sql oracle duplicates

好吧我说有一个票证表,用户表,角色表和role_mapping表。票证由用户拥有。用户可以拥有1个或多个角色。 roles表定义角色,而role_mapping表将用户映射到他/她的角色(角色基本上是权限)。所以我想要做的是加入用户,票证和角色映射(Oracle SQL):

SELECT t.ticket_id, u.user_id, rm.role_id
FROM tickets t
JOIN users u on u.user_id = t.user_id
JOIN role_mappings rm on rm.user_id = u.user_id
WHERE ...

因此,如果给定用户具有多个角色,那么这当然会生成具有相同ticket_id的多行。我想要的是,如果role_id是'102',只生成一行值为'102',否则,只生成一行对应给定用户的最大角色值,即如果用户有role_id 101,102,105则选择102 ,但如果是101,105则选择105。

这是如何实现的?

1 个答案:

答案 0 :(得分:1)

我认为你在你的例子中犯了一个错误(当你的101,102,105与你的书面描述不一致时选择了102) - 但你在联接和使用聚合函数后所寻找的是group bymax)选择你的最大价值角色。类似的东西:

SELECT t.ticket_id, u.user_id, max(rm.role_id)
FROM tickets t
JOIN users u on u.user_id = t.user_id
JOIN role_mappings rm on rm.user_id = u.user_id
WHERE ...
GROUP BY t.ticket_id, u.user_id

如果您想要一行中的所有角色,请查看GROUP_CONCAT

<强>更新

要满足角色102的要求,首选方法是排除具有角色102的故障单用户的结果,然后使用union

在第二个查询中添加它们

这样的事情:

SELECT t.ticket_id, u.user_id, max(rm.role_id)
FROM tickets t
JOIN users u on u.user_id = t.user_id
JOIN role_mappings rm on rm.user_id = u.user_id
WHERE u.user_id NOT IN (
     SELECT t.ticket_id, u.user_id, max(rm.role_id)
     FROM tickets t
     JOIN users u on u.user_id = t.user_id
     JOIN role_mappings rm on rm.user_id = u.user_id
     WHERE rm.role_id = 102)
GROUP BY u.id

UNION ALL 

SELECT t.ticket_id, u.user_id, rm.role_id
FROM tickets t
JOIN users u on u.user_id = t.user_id
JOIN role_mappings rm on rm.user_id = u.user_id
WHERE rm.role_id=102

这里没有票表:http://sqlfiddle.com/#!2/cc1c6/5