【问题标题】:SQL Group By with a condition带条件的 SQL 分组依据
【发布时间】:2011-08-16 18:07:27
【问题描述】:

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

用户名、名字、姓氏、目录、角色、访问权限、 上次登录日期

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

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

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

编辑:我应该解释得更好。我仍然需要拒绝行来显示目录中是否不允许用户。但如果它们被允许,那么显示拒绝行就没有意义了。

【问题讨论】:

  • 为什么不能在查询中添加“where access = 'allow'”?
  • 我应该备份...您的查询是什么样的?
  • @Ramy,请阅读我在解释中不清楚的编辑。
  • 我还是不清楚。我将 GISMO 视为目录两次(第 6 行和第 7 行),但角色不同。拒绝 test_user 并允许 gismo_user。结果应该是什么?
  • 您可以修改您的 .NET 解析例程以避免插入重复项,这可能吗?

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


【解决方案1】:

这适用于 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        

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

【讨论】:

  • 在 SQL Server 世界中,您不能使用 UNIQUE,但可以使用 DISTINCT。
【解决方案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

【讨论】:

  • 你的意思是order by Access吗?我认为这样会更有意义。
【解决方案3】:

这样的事情应该可以工作,但这假设您没有输入路径,例如 /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

【讨论】:

    【解决方案4】:
    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
             )
          )
    

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

                 AND R2.Roles = R.Roles
    

    【讨论】:

      猜你喜欢
      • 2017-09-10
      • 2010-09-06
      • 2022-12-12
      • 2010-11-28
      • 1970-01-01
      • 2018-12-20
      • 2018-11-26
      • 1970-01-01
      • 2012-05-18
      相关资源
      最近更新 更多