多个连接后删除重复

时间:2018-05-18 16:43:19

标签: sql postgresql

有多个表格:

项目→items_roles→角色

项目→区域→roles_zones→角色

items: id, zone_id
items_roles: role_id, item_id
zones: id
roles_zones: role_id, zone_id
roles: id, role_type_id, 

我正在尝试将角色字段添加到项目中,它应该采用role_type,如果它是项目区域(roles_zones)中的NULL获取回退值,则它是来自items_zones anf的值。

我创建了这个查询:

SELECT
    items.id,
    z_roles.role_type_id as z_role_type_id, z_roles.id as z_role_id,
    i_roles.role_type_id as i_role_type_id, i_roles.id as i_role_id
  FROM items

  LEFT JOIN zones as j_zones ON j_zones.id = items.zone_id
  LEFT JOIN roles_zones ON roles_zones.zone_id = j_zones.id
  LEFT JOIN roles as z_roles ON (z_roles.id = roles_zones.role_id)

  LEFT JOIN items_roles ON items_roles.item_id = items.id
  LEFT JOIN roles as i_roles ON items_roles.role_id = i_roles.id
  AND (z_roles.role_type_id = i_roles.role_type_id)

  WHERE items.id = 834

  ORDER BY i_roles.id;

结果我看到了:

id  | z_role_type_id | z_role_id | i_role_type_id | i_role_id 
-----+----------------+-----------+----------------+-----------
 834 |              5 |       111 |              5 |        68
 834 |             11 |       120 |             11 |       120
 834 |              7 |        77 |                |          
 834 |             12 |        91 |                |          
 834 |              4 |        78 |                |          
 834 |              2 |         2 |                |          
 834 |              5 |       111 |                |          
 834 |              8 |        36 |                |          
 834 |              8 |        36 |                |          
 834 |             12 |        91 |                |          
 834 |              4 |        78 |                |          
 834 |              2 |         2 |                |          
 834 |             11 |       120 |                |          
 834 |              7 |        77 |                |          
(14 rows)

有14行,我只需要7行。

例如两行:

id  | z_role_type_id | z_role_id | i_role_type_id | i_role_id
834 |              5 |       111 |              5 |        68
834 |              5 |       111 |                |    

如果已存在包含这些值的行,我想删除空i_role_type_idi_role_id的行。

这是期望的输出:

id  | z_role_type_id | z_role_id | i_role_type_id | i_role_id 
-----+----------------+-----------+----------------+-----------
 834 |              5 |       111 |              5 |        68
 834 |             11 |       120 |             11 |       120
 834 |              7 |        77 |                |          
 834 |             12 |        91 |                |          
 834 |              4 |        78 |                |          
 834 |              2 |         2 |                |         
 834 |              8 |        36 |                |          
(7 rows)

如何重写查询?

现在可行:

SELECT items.id
  ,z_roles.role_type_id as z_role_type_id
  ,z_roles.id as z_role_id
  ,MAX(i_roles.role_type_id) as i_role_type_id
  ,MAX(i_roles.id) as i_role_id
FROM items

LEFT JOIN zones as j_zones ON j_zones.id = items.zone_id
LEFT JOIN roles_zones ON roles_zones.zone_id = j_zones.id
LEFT JOIN roles as z_roles ON (z_roles.id = roles_zones.role_id)

LEFT JOIN items_roles ON items_roles.item_id = items.id
LEFT JOIN roles as i_roles ON items_roles.role_id = i_roles.id
AND (z_roles.role_type_id = i_roles.role_type_id)

WHERE items.id = 834
Group By items.id, z_roles.role_type_id, z_roles.id
ORDER BY items.id, i_role_id;

结果:

 id  | z_role_type_id | z_role_id | i_role_type_id | i_role_id 
-----+----------------+-----------+----------------+-----------
 834 |              5 |       111 |              5 |        68
 834 |             11 |       120 |             11 |       120
 834 |              7 |        77 |                |          
 834 |              2 |         2 |                |          
 834 |             12 |        91 |                |          
 834 |              4 |        78 |                |          
 834 |              8 |        36 |                |          
(7 rows)

1 个答案:

答案 0 :(得分:1)

在您的select语句中,您只需要一个简单的 Group By 来聚合数据。

  

分组items.id,z_roles.role_type_id,z_roles.id

具体而言;

 SELECT items.id
  ,z_roles.role_type_id as z_role_type_id
  ,z_roles.id as z_role_id
  ,MAX(i_roles.role_type_id) as i_role_type_id
  ,MAX(i_roles.id) as i_role_id
FROM items

LEFT JOIN zones as j_zones ON j_zones.id = items.zone_id
LEFT JOIN roles_zones ON roles_zones.zone_id = j_zones.id
LEFT JOIN roles as z_roles ON (z_roles.id = roles_zones.role_id)

LEFT JOIN items_roles ON items_roles.item_id = items.id
LEFT JOIN roles as i_roles ON items_roles.role_id = i_roles.id
AND (z_roles.role_type_id = i_roles.role_type_id)

WHERE items.id = 834
Group By items.id, z_roles.role_type_id, z_roles.id
ORDER BY i_roles.id;