2015-05-12 65 views
-1

我有两个表,其中一个包含来自某些应用程序的访问历史记录,另一个包含执行这些访问的用户的访问历史记录。基于两个表的复杂查询

ACCESS_HISTORY 
WORKSPACE - APP_ID - APP_NAME - USERNAME 

WS_1  1  APP_NAME  USER_1 
WS_1  1  APP_NAME  USER_2 
WS_2  1  APP_NAME  USER_3 
WS_3  2  APP_NAME  USER_1 

USERS 
WORKSPACE - USERNAME - IS_ADMIN - IS_DEVELOPER 
WS_1  USER_1  YES   NO 
WS_1  USER_2  NO   YES 
WS_2  USER_3  NO   NO 
WS_3  USER_1  NO   YES 

我想执行一个SELECT查询来获取每个应用程序(详细登记信息acc_general是获得来自谁不是管理员或开发人员的用户数量,acc_adm是从管理用户的访问,acc_dev是从开发用户的访问,并acc_total一般,ADM和DEV访问)的总和:

WORKSPACE APP_NAME APP_ID ACC_GENERAL ACC_ADM ACC_DEV ACC_TOTAL 
WS_1  APP_NAME 1  0   1  1  2 
WS_2  APP_NAME 1  1   0  0  1 
WS_3  APP_NAME 2  0   0  1  1 

需要注意的是:

  • access_history中,当工作空间和app_id相同时,访问引用相同的应用程序。两个应用程序可能具有相同的ID,但位于不同的工作区中。
  • 每个USERNAME都是指同一个用户,但用户可能是管理员或开发人员,并且只能是另一个工作区上的简单用户。
  • 真正的数据库包含许多行(700K +上ACCESS_HISTORYUSERS5K)等多个栏目,但现在这并不重要。
  • 我正在使用Oracle数据库。
  • 如果有人想请编辑我的问题标题更多的拨款(我想不出一个更好的)。
+2

什么是您当前的查询是什么样子?什么部分给你带来麻烦? –

回答

1

SQL Fiddle

的Oracle 11g R2架构设置

CREATE TABLE ACCESS_HISTORY AS 
      SELECT 'WS_1' AS WORKSPACE, 1 AS APP_ID, 'APP_NAME' AS APP_NAME, 'USER_1' AS USERNAME FROM DUAL 
UNION ALL SELECT 'WS_1' AS WORKSPACE, 1 AS APP_ID, 'APP_NAME' AS APP_NAME, 'USER_2' AS USERNAME FROM DUAL 
UNION ALL SELECT 'WS_2' AS WORKSPACE, 1 AS APP_ID, 'APP_NAME' AS APP_NAME, 'USER_3' AS USERNAME FROM DUAL 
UNION ALL SELECT 'WS_3' AS WORKSPACE, 2 AS APP_ID, 'APP_NAME' AS APP_NAME, 'USER_1' AS USERNAME FROM DUAL; 

CREATE TABLE USERS AS 
      SELECT 'WS_1' AS WORKSPACE, 'USER_1' AS USERNAME, 'YES' AS IS_ADMIN, 'NO' AS IS_DEVELOPER FROM DUAL 
UNION ALL SELECT 'WS_1' AS WORKSPACE, 'USER_2' AS USERNAME, 'NO' AS IS_ADMIN, 'YES' AS IS_DEVELOPER FROM DUAL 
UNION ALL SELECT 'WS_2' AS WORKSPACE, 'USER_3' AS USERNAME, 'NO' AS IS_ADMIN, 'NO' AS IS_DEVELOPER FROM DUAL 
UNION ALL SELECT 'WS_3' AS WORKSPACE, 'USER_1' AS USERNAME, 'NO' AS IS_ADMIN, 'YES' AS IS_DEVELOPER FROM DUAL; 

查询1

SELECT a.WORKSPACE, 
     a.APP_NAME, 
     a.APP_ID, 
     COUNT(CASE WHEN u.IS_ADMIN <> 'YES' AND u.IS_DEVELOPER <> 'YES' THEN 1 END) AS ACC_GENERAL, 
     COUNT(CASE u.IS_ADMIN WHEN 'YES' THEN 1 END) AS ACC_ADM, 
     COUNT(CASE u.IS_DEVELOPER WHEN 'YES' THEN 1 END) AS ACC_DEV, 
     COUNT(1) AS ACC_TOTAL 
FROM ACCESS_HISTORY a 
     INNER JOIN 
     USERS u 
     ON ( a.WORKSPACE = u.WORKSPACE 
      AND a.USERNAME = u.USERNAME) 
GROUP BY 
     a.WORKSPACE, 
     a.APP_NAME, 
     a.APP_ID 

Results

| WORKSPACE | APP_NAME | APP_ID | ACC_GENERAL | ACC_ADM | ACC_DEV | ACC_TOTAL | 
|-----------|----------|--------|-------------|---------|---------|-----------| 
|  WS_1 | APP_NAME |  1 |   0 |  1 |  1 |   2 | 
|  WS_2 | APP_NAME |  1 |   1 |  0 |  0 |   1 | 
|  WS_3 | APP_NAME |  2 |   0 |  0 |  1 |   1 | 
0

尝试这样:

SELECT h.workspace, h.appid, h.appname, u.username, 
SUM(CASE WHEN u.is_admin=0 AND u.is_dev=0 THEN 1 ELSE 0 END) AS acc_general, 
SUM(CASE WHEN u.is_admin>0 THEN 1 ELSE 0 END) AS acc_admin, 
SUM(CASE WHEN u.is_dev>0 THEN 1 ELSE 0 END) acc_dev, COUNT(*) AS acc_total 
FROM acc_history h LEFT JOIN users u 
ON h.worksapce=u.workspace AND h.username=u.workspace 
GROUP BY h.workspace, h.appid, h.appname, u.username