SQL Group By带条件

时间:2011-08-16 18:07:27

标签: asp.net sql-server vb.net group-by

场景:我需要为ASP.Net应用程序的审核员创建报告。我有一个程序解析授权标记的目录中的web.config文件的XML,并创建一个报告,提供哪些用户可以访问站点结构中的哪个文件夹。报告如下所示。

  

UserName,Firstname,LastName,Directory,Roles,Access,   LastLoginDate

enter image description here

问题:从报告中可以看到一些目录(其中包含GISMO的中间列)显示两次,同时允许和拒绝用户。我想知道是否有一种方法可以对结果进行分组,如果有一行允许一个目录,那么deny's不会显示,但不会显示。

或者如果这可以在VB.net/C#中操作,这也是一个选项。它回到那里并被泵入Excel电子表格。

感谢任何帮助。提前谢谢。

编辑:我应该更好地解释一下。我仍然需要拒绝行来显示目录中是否允许用户。但是,如果他们被允许,那么没有任何一点显示拒绝行。

4 个答案:

答案 0 :(得分:4)

这适用于Oracle数据库,所以它应该可以工作,或者让我关闭SQL Server,因为我知道SQL Server 支持这个主要组件,即CASE操作。

CREATE TABLE user_permissions (
     user_role   VARCHAR2(10) NOT NULL,
     dir         VARCHAR2(10) NOT NULL,
     user_access VARCHAR2(5)  NOT NULL
);

INSERT INTO user_permissions VALUES ('admin', 'dir1', 'allow');
INSERT INTO user_permissions VALUES ('admin', 'dir2', 'allow');
INSERT INTO user_permissions VALUES ('power', 'dir1', 'allow'); -- Allow and Deny dir1
INSERT INTO user_permissions VALUES ('power', 'dir1', 'deny');
INSERT INTO user_permissions VALUES ('power', 'dir2', 'deny');
COMMIT;


SELECT UNIQUE j.*
FROM (
       SELECT user_role, dir,
              MAX(CASE user_access WHEN 'allow' THEN 1 ELSE 0 END) allowFlag,
              MAX(CASE user_access WHEN 'deny'  THEN 1 ELSE 0 END) denyFlag
       FROM user_permissions
       GROUP BY user_role, dir
     ) t
JOIN user_permissions j ON (t.user_role = j.user_role AND t.dir = j.dir)
WHERE j.user_access = 'allow' OR (t.allowFlag = 0 and user_access = 'deny');

<强>结果:

USER_ROLE  DIR        USER_ACCESS 
---------- ---------- ----------- 
admin      dir1       allow       
admin      dir2       allow       
power      dir1       allow       
power      dir2       deny        

基本上,您使用数据透视表将多行聚合到一行中,描述目录的属性。获得聚合行后,可以轻松比较您声明的属性以连接要显示的行。

答案 1 :(得分:2)

如果你有SQL Server 2005或更新版本,你可以使用它:

with cte as (
    select ROW_NUMBER() OVER (partition by username, directory order by access) as row, *
    from report
)
select *
from cte
where row = 1

在分区子句中,放入任何使“组”唯一的东西。

参考: http://msdn.microsoft.com/en-us/library/ms190766.aspx

http://msdn.microsoft.com/en-us/library/ms186734.aspx

答案 2 :(得分:1)

这样的东西应该可以工作,但这假设你的路径没有输入,如/ directory / directory /,/ directory / Directory /,directory / directory / default.aspx等。最好的办法是解析数据并删除您创建的.NET进程级别的重复项,因为在该阶段进行解析通常更容易。

select derived.*,
       case when exists 
         (select top 1 1 from table_name as t2 where t2.username = derived.username and t2.directory=derived.directory and t2.access = 'allow') then 1 else 0 end as is_allowed,
       case when exists 
         (select top 1 1 from table_name as t2 where t2.username = derived.username and t2.directory=derived.directory and t2.access = 'deny') then 1 else 0 end as is_denied,
from
(
 select distinct t.username, t.firstname, t.lastname, t.directory
  from table_name as t
) as derived

答案 3 :(得分:1)

SELECT UserName, Firstname, LastName, Directory, Roles, Access, LastLoginDate 
FROM Report R
WHERE Access = 'allow'
   OR ( Access = 'deny' 
      AND NOT EXISTS
         ( SELECT *
           FROM Report R2
           WHERE R2.Directory = R.Directory
             AND R2.UserName = R.UserName 
             AND R2.Roles = R.Roles
         )
      )

根据您的评论,应删除此行,因此仅检查(UserName, Directory)组合:

             AND R2.Roles = R.Roles