4

次のテーブルがあります。

ユーザー・グループ

usergrp_id      bigint     Primary Key
usergrp_name    text  

ユーザー

user_id             bigint     Primary Key
user_name           text
user_usergrp_id     bigint
user_loc_id         bigint

user_usergrp_iduser_group テーブルからの対応する ID を user_loc_id持ち、branch テーブルからの対応する ID (branch_id) を持ちます。

ブランチ

branch_id      bigint     Primary Key
branch_name    text
branch_type    smallint

branch_typeデフォルトでは 1 に設定されています。ただし、1 から 4 までの任意の値が含まれる場合があります。

ユーザー_プロジェクト

proj_id          bigint     Primary Key
proj_name        text
proj_branch_id   smallint

proj_branch_idブランチ テーブルからの対応する id(branch_id) を持っています。

ユーザー承認

appr_id           bigint     Primary Key
appr_prjt_id      bigint
appr_status       smallint
appr_approval_by  bigint

appr_approval_byuser テーブルからの対応する id(user_id)
appr_statusには、単一の 10、20、30 などのさまざまなステータス値が含まれる場合があります。appr_prjt_id

ユーザー・グループ

usergrp_id | usergrp_name
-------------------------
    1      | Admin
    2      | Manager

ユーザー

user_id | user_name | user_usergrp_id |user_loc_id
---------------------------------------------------
    1   | John      |      1          |     1
    2   | Harry     |      2          |     1

ブランチ

branch_id | branch_name | branch_type
-------------------------------------
    1     |  location1  |    2
    2     |  location2  |    1
    3     |  location3  |    4
    4     |  location4  |    2
    5     |  location4  |    2

ユーザー_プロジェクト

proj_id | proj_name | proj_branch_id
------------------------------------
    1   | test1      |       1
    2   | test2      |       2
    3   | test3      |       1
    4   | test4      |       3
    5   | test5      |       1
    6   | test5      |       4

ユーザー承認

appr_id | appr_prjt_id | appr_status | appr_approval_by
-------------------------------------------------------
    1   |    1         |     10      |     1
    2   |    1         |     20      |     1
    3   |    1         |     30      |     1
    4   |    2         |     10      |     2
    5   |    3         |     10      |     1
    6   |    3         |     20      |     2
    7   |    4         |     10      |     1
    8   |    4         |     20      |     1

条件:出力はfor eachのMAX()値を取り、それをカウントする必要があります。appr_statusappr_prjt_id

つまり、上記の表では、10、20、30 のappr_prjt_id=13 つの異なるステータスがあります。そのカウントは、特定のユーザー グループに対応する、出力の 30 に対応するステータス (ステータス 10 および 20 ではなく) に対してのみ表示する必要がありますbranch_name。同様に、フィールド内の他の各 ID についてもappr_prjt_id

SQL フィドル

望ましい出力:

                           10   |    20  |  30

         ------> Admin     0    |    1   |   1
         |
location1
         |
         ------> Manager   1    |    1   |   0

どうやってやるの?

SQL フィドル

4

1 に答える 1

2

SQL フィドル

select
    branch_name, usergrp_name,
    sum((appr_status = 10)::integer) "10",
    sum((appr_status = 20)::integer) "20",
    sum((appr_status = 30)::integer) "30"
from
    (
        select distinct on (appr_prjt_id)
            appr_prjt_id, appr_approval_by, appr_status
        from user_approval
        order by 1, 3 desc
    ) ua
    inner join
    users u on ua.appr_approval_by = u.user_id
    inner join
    user_group ug on u.user_usergrp_id = ug.usergrp_id
    inner join
    branch b on u.user_loc_id = b.branch_id
group by branch_name, usergrp_name
order by usergrp_name

ほとんどの DBMS で機能する古典的な解決策は、次を使用することcaseです。

select
    branch_name, usergrp_name,
    sum(case appr_status when 10 then 1 else 0 end) "10",

しかし、Postgresql にはブール型があり、integer ( boolean::integer) へのキャストがあり、結果として 0 または 1 になるため、冗長なコードが少なくなります。

countこの場合、 aの代わりに inを実行することも可能ですsum:

select
    branch_name, usergrp_name,
    count(appr_status = 10 or null) "10",

確かに の方countが好きですが、分かりにくい印象があります。トリックは、 がcountnull 以外のものをカウントし、 (trueまたは null) が null でtrueあり、 (falseまたは null) が null であることを知っているため、条件が真の場合は常にカウントされます。

于 2013-03-28T08:19:29.177 に答える