检索聚合列表的PostgreSQL查询

时间:2013-04-08 20:22:40

标签: postgresql

我有四个表Users,Roles,User_Role和Email。我需要开发一个查询来检索用户信息(用户名,姓氏和名字),用户电子邮件地址(来自电子邮件表)和所有角色的汇总列表(连接到具有多个用户的用户表) to-many table user_role)。我开发了下面的查询,其中有一个问题。聚合列表具有重复的角色名称条目。

SELECT DISTINCT ON (u.username)
    u.username AS "Username", u.lastname AS "Last Name", u.firstname AS "First Name", e.name AS "Email Address"
    , string_agg(r.name, ';'  ORDER BY r.name) AS "Roles"
FROM    users u
    LEFT OUTER JOIN user_role ur ON (u.id=ur.user_id)
    LEFT OUTER JOIN roles r ON (ur.role_id = r.id)
    INNER JOIN email e ON e.user_id = u.id
WHERE   u.active = 1 AND length(r.name) > 0 AND r.active = 1 AND ur.active = 1
GROUP BY u.username, u.lastname, u.firstname, e.name
ORDER BY u.username

如果我注释掉内部电子邮件加入和关联的电子邮件字段(见下文),我会在string_agg中获得正确的角色名称。

SELECT DISTINCT ON (u.username)
    u.username AS "Username", u.lastname AS "Last Name", u.firstname AS "First Name",
--  e.name AS "Email Address"
    , string_agg(r.name, ';'  ORDER BY r.name) AS "Roles"
FROM    users u
    LEFT OUTER JOIN user_role ur ON (u.id=ur.user_id)
    LEFT OUTER JOIN roles r ON (ur.role_id = r.id)
--  INNER JOIN email e ON e.user_id = u.id
WHERE   u.active = 1 AND length(r.name) > 0 AND r.active = 1 AND ur.active = 1
GROUP BY u.username, u.lastname, u.firstname, 
--  e.name
ORDER BY u.username

1 个答案:

答案 0 :(得分:0)

这可能会解决问题。这是一个有根据的猜测。问题中的信息不足。

SELECT DISTINCT ON (u.username)
        u.username AS "Username"
      , u.lastname AS "Last Name"
      , u.firstname AS "First Name"
      , e.emails AS "Email Addresses"
      , string_agg(r.name, ';'  ORDER BY r.name) AS "Roles"
FROM    users u
LEFT    JOIN user_role ur ON u.id = ur.user_id
LEFT    JOIN roles     r  ON ur.role_id = r.id
LEFT    JOIN (
   SELECT user_id, string_agg(name, ', ') AS emails
   FROM   email
   GROUP  BY 1
   ) e  ON e.user_id = u.id
WHERE  u.active = 1
AND    r.name  ''
AND    r.active = 1
AND    ur.active = 1
GROUP  BY u.username, u.lastname, u.firstname, e.emails 
ORDER  BY u.username

除此之外:r.name <> ''length(r.name) > 0的效果相同,速度更快。

对于电子邮件而不是LEFT JOIN,这应该是JOIN是一个无关的问题。
但我想它应该是,所以我也改变了。