6

私は既存のデータベースを使用していて、SQLクエリを作成して、アクセス許可レベルを含むすべてのアカウント情報を取得しようとしています。これはセキュリティ監査用です。比較しやすいように、このすべての情報を読みやすい方法でダンプしたいと思います。私の問題は、アクセス許可用のブリッジ/リンクテーブルがあるため、ユーザーごとに複数のレコードがあることです。1行で1人のユーザーのすべての権限を使用して結果を取得したいと思います。次に例を示します。

Table_User:
UserId   UserName
1        John
2        Joe
3        James

Table_UserPermissions:
UserId   PermissionId   Rights
1        10             1
1        11             2
1        12             3
2        11             2
2        12             3
3        10             2

PermissionIDは、Permissionの名前とその機能を備えたテーブルにリンクします。右は、1 =表示、2=変更などのようなものです。

ユーザー1の基本的なクエリから返されるのは次のとおりです。

UserId UserName PermissionId Rights
1      John     10           1
1      John     11           2
1      John     12           3

私はこのようなものが欲しいです:

UserId UserName Permission1 Rights1 Permission2 Right2 Permission3 Right3
1      John     10          1       11          2      12          3

理想的には、これをすべてのユーザーに提供したいと思います。私が見つけた最も近いものは、SQL Server 2005のピボット関数です。http : //geekswithblogs.net/lorint/archive/2006/08/04/87166.aspx 私が言えることから、これに関する問題は、私が必要としていることです。各ユーザーの各列に名前を付けると、権限レベルを取得する方法がわかりません。実際のデータでは、約130人のユーザーと40の異なる権限があります。

私がこれを行うことができるSQLだけで別の方法はありますか?

4

8 に答える 8

3

あなたはこのようなことをすることができます:

select userid, username
,      max(case when permissionid=10 then rights end) as permission10_rights
,      max(case when permissionid=11 then rights end) as permission11_rights
,      max(case when permissionid=12 then rights end) as permission12_rights
from   userpermissions
group by userid, username;

パーミッションIDごとに同様のmax(...)列を明示的に追加する必要があります。

于 2008-11-18T17:38:49.887 に答える
2

MySQL を使用している場合は、以下のようにgroup_concat()を使用することをお勧めします。

select UserId, UserName, 
       group_concat(PermissionId) as PermIdList,
       group_concat(Rights SEPARATOR ',') as RightsList
from Table_user join Table_UserPermissions on 
     Table_User.UserId = Table_UserPermissions.UserId=
GROUP BY Table_User.UserId

これは戻ります

UserId UserName PermIdList  RightsList
1      John     10,11,12    1,2,3

「mssql group_concat」を Google ですばやく検索すると、同じ動作を実現できる MSSQL用のいくつかの異なるストアド プロシージャ ( I )、( II ) が明らかになりました。

于 2008-11-19T01:33:50.973 に答える
1

短い答え:

いいえ。

クエリに列を動的に追加することはできません。

SQLはセットベースの言語であることを忘れないでください。セットを照会し、セットを結合します。

あなたが掘り出しているのは再帰的なリストであり、リストを垂直方向ではなく水平方向につなぎ合わせる必要があります。

一連の自己結合を使用して、それを偽造することができますが、それを行うには、クエリを作成する前に、考えられるすべての権限を知っている必要があります...これは他の提案が提案していることです。

レコードセットを別の言語にプルバックし、それを繰り返して適切な列を生成することもできます。

何かのようなもの:

SELECT Table_User.userID, userName, permissionid, rights
FROM Table_User
        LEFT JOIN Table_UserPermissions ON Table_User.userID =Table_UserPermissions.userID
ORDER BY userName

次に、(Python)のようなものを使用して、各ユーザーのすべてのアクセス許可を表示します。

userID = recordset[0][0]
userName = recordset[0][1]
for row in recordset:
   if userID != row[0]:
       printUserPermissions(username, user_permissions)
       user_permissions = []
       username = row[1]
       userID = row[0]

    user_permissions.append((row[2], row[3]))

printUserPermissions(username, user_permissions)
于 2008-11-18T17:52:58.407 に答える
0

それが許容できる場合、設計および/または実装の両方で私が使用した戦略は、ピボットされていないクエリを Excel または Access にダンプすることです。どちらも、データをピボットするためのより使いやすい UI を備えており、より多くの人がその環境に慣れています。

気に入ったデザインができたら、それを TSQL で複製する方法を考えるのは簡単です。

于 2008-11-18T18:30:26.290 に答える
0

ピボット関数は、フィールドの 1 つで集計関数を使用できる状況向けに設計されたようです。たとえば、会社 x の各営業担当者の収益を知りたいとします。販売テーブルから価格フィールドを合計できます。次に、営業担当者と、その営業担当者の売上高を取得します。アクセス許可については、permissionId フィールドまたは Rights フィールドを合計/カウント/などしても意味がありません。

于 2008-11-18T18:51:47.370 に答える
0

次の一時的な table_flatuserpermissions を作成できます。

ユーザーID
権限ID1
権利1
権限ID2
権利2
...など、必要な数の許可/権利の組み合わせに

すべての許可と権限のフィールドを null にして、Table_user からこのテーブルにレコードを挿入します。

このテーブルのレコードを table_userpermissions から更新します - 最初のレコードを挿入して PermissionID1 と Rights1 を設定し、ユーザーの 2 番目のレコードを PermissionsID2 と Rights2 などに更新します。

次に、このテーブルにクエリを実行してレポートを生成します。

個人的には、現在の UserId、UserName、PermissionID、Rights 列に固執します。

数値の代わりに、PermissionID と Rights を何らかのテキストに置き換えることもできます。

おそらく、テーブルを PermissionID、User ではなく User、PermissionID でソートして、監査人が各権限タイプのユーザーをチェックできるようにします。

于 2008-11-18T17:41:12.440 に答える
0

SQL でクロス集計クエリを作成する場合は、次の例を参照してください。

http://www.databasejournal.com/features/mssql/article.php/3521101/Cross-Tab-reports-in-SQL-Server-2005.htm

PIVOT および UNPIVOT と呼ばれる SQL Server 2005 の一部として含まれていた新しい操作があるようです。

于 2008-11-18T19:02:54.693 に答える
0

UNPIVOTこのタイプのデータ変換では、データのとの両方を実行する必要がありPIVOTます。変換する値がわかっている場合は、静的ピボットを使用してクエリをハードコーディングできます。それ以外の場合は、動的 SQL を使用できます。

テーブルを作成します。

CREATE TABLE Table_User
    ([UserId] int, [UserName] varchar(5))
;

INSERT INTO Table_User
    ([UserId], [UserName])
VALUES
    (1, 'John'),
    (2, 'Joe'),
    (3, 'James')
;

CREATE TABLE Table_UserPermissions
    ([UserId] int, [PermissionId] int, [Rights] int)
;

INSERT INTO Table_UserPermissions
    ([UserId], [PermissionId], [Rights])
VALUES
    (1, 10, 1),
    (1, 11, 2),
    (1, 12, 3),
    (2, 11, 2),
    (2, 12, 3),
    (3, 10, 2)
;

静的ピボット:

select *
from
(
  select userid,
    username,
    value,
    col + '_'+ cast(rn as varchar(10)) col
  from
  (
    select u.userid,
      u.username,
      p.permissionid,
      p.rights,
      row_number() over(partition by u.userid 
                        order by p.permissionid, p.rights) rn
    from table_user u
    left join Table_UserPermissions p
      on u.userid = p.userid
  ) src
  unpivot
  (
    value
    for col in (permissionid, rights)
  ) unpiv
) src
pivot
(
  max(value)
  for col in (permissionid_1, rights_1, 
              permissionid_2, rights_2, 
              permissionid_3, rights_3)
) piv
order by userid

デモで SQL Fiddle を参照してください

動的ピボット:

permissionidおよび の数が不明な場合は、rights動的 SQL を使用できます。

DECLARE 
    @query  AS NVARCHAR(MAX),
    @colsPivot as  NVARCHAR(MAX)

select @colsPivot = STUFF((SELECT  ',' 
                      + quotename(c.name +'_'+ cast(t.rn as varchar(10)))
                    from
                    (
                      select row_number() over(partition by u.userid 
                                order by p.permissionid, p.rights) rn
                      from table_user u
                      left join Table_UserPermissions p
                        on u.userid = p.userid
                    ) t
                    cross apply sys.columns as C
                   where C.object_id = object_id('Table_UserPermissions') and
                         C.name not in ('UserId')
                   group by c.name, t.rn
                   order by t.rn
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query 
  = 'select *
     from
     (
       select userid,
         username,
         value,
         col + ''_''+ cast(rn as varchar(10)) col
       from
       (
         select u.userid,
           u.username,
           p.permissionid,
           p.rights,
           row_number() over(partition by u.userid 
                             order by p.permissionid, p.rights) rn
         from table_user u
         left join Table_UserPermissions p
           on u.userid = p.userid
       ) src
       unpivot
       (
         value
         for col in (permissionid, rights)
       ) unpiv
     ) x1
     pivot
     (
       max(value)
       for col in ('+ @colspivot +')
     ) p
     order by userid'

exec(@query)

デモで SQL Fiddle を参照してください

両方の結果は次のとおりです。

| USERID | USERNAME | PERMISSIONID_1 | RIGHTS_1 | PERMISSIONID_2 | RIGHTS_2 | PERMISSIONID_3 | RIGHTS_3 |
---------------------------------------------------------------------------------------------------------
|      1 |     John |             10 |        1 |             11 |        2 |             12 |        3 |
|      2 |      Joe |             11 |        2 |             12 |        3 |         (null) |   (null) |
|      3 |    James |             10 |        2 |         (null) |   (null) |         (null) |   (null) |
于 2012-12-21T15:09:49.980 に答える