0

Users、Roles、User_Role、および Email の 4 つのテーブルがあります。ユーザー情報 (ユーザー名、姓、名)、ユーザーの電子メール アドレス (電子メール テーブルから)、およびすべてのロールの集計リスト (多数のユーザー テーブルに接続されている) を取得するクエリを作成する必要があります。対多テーブル user_role)。以下のクエリを作成しましたが、これには 1 つの問題があります。集約されたリストに重複するロール名エントリがあります。

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
4

1 に答える 1

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は、無関係な問題です。
でも、そうあるべきだと思うので、それも変更しました。

于 2013-04-08T23:06:05.730 に答える