之前我问过这个question,但是从评论中我意识到问题不足以获得帮助,所以我在这里提供整个查询+解释计划:
查询:
WITH gtt_1 AS
(SELECT
r.user_id, r.role_id, r.participant_code, MAX(status_id)
FROM
user_role r,
cmp_role c
WHERE
r.role_id = c.role_id
AND r.participant_code IS NOT NULL
AND c.group_id = 3
GROUP BY
r.user_id, r.role_id, r.participant_code
HAVING MAX(status_id) IN (SELECT b.status_id FROM USER_ROLE b
WHERE (b.ACTIVE = 1 OR ( b.ACTIVE IN ( 0,3 )
AND SYSDATE BETWEEN b.effective_from_date AND b.effective_to_date
))
)
)
SELECT c.role_id,
c.subgroup,
c.subgroup_description,
COUNT(a.USER_ID) user_count
FROM
(SELECT b.user_id, b.role_id FROM gtt_1 b, user e
WHERE e.user_id = RTRIM(b.user_id)
) a
RIGHT OUTER JOIN CMP_ROLE c ON a.role_id = c.role_id
WHERE c.group_id = 3
GROUP BY c.role_id,c.subgroup,c.subgroup_description
ORDER BY c.subgroup;
使用的表:
SQL> select count(*) from user_role;
COUNT(*)
----------
803513
SQL> select count(*) from cmp_role;
COUNT(*)
----------
27
SQL> select count(*) from user;
COUNT(*)
----------
73893
解释计划:
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 269840545
--------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Inst |IN-OUT|
--------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 256 | 18944 | 1683 (4)| 00:00:21 | | |
| 1 | SORT GROUP BY | | 256 | 18944 | 1683 (4)| 00:00:21 | | |
|* 2 | HASH JOIN OUTER | | 2776 | 200K| 1682 (4)| 00:00:21 | | |
| 3 | TABLE ACCESS BY INDEX ROWID | ROLE | 8 | 504 | 2 (0)| 00:00:01 | | |
|* 4 | INDEX RANGE SCAN | N_ROLE_IDX2 | 8 | | 1 (0)| 00:00:01 | | |
| 5 | VIEW | | 9370 | 100K| 1683 (5)| 00:00:21 | | |
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------
| 6 | NESTED LOOPS | | 9370 | 164K| 1683 (5)| 00:00:21 | | |
| 7 | VIEW | | 9370 | 100K| 1677 (4)| 00:00:21 | | |
|* 8 | FILTER | | | | | | | |
| 9 | HASH GROUP BY | | 9370 | 283K| 1677 (4)| 00:00:21 | | |
|* 10 | HASH JOIN | | 232K| 7051K| 1654 (3)| 00:00:20 | | |
| 11 | TABLE ACCESS BY INDEX ROWID| ROLE | 8 | 56 | 2 (0)| 00:00:01 | | |
|* 12 | INDEX RANGE SCAN | N_ROLE_IDX2 | 8 | | 1 (0)| 00:00:01 | | |
|* 13 | TABLE ACCESS FULL | USER_ROLE | 786K| 17M| 1643 (2)| 00:00:20 | | |
|* 14 | TABLE ACCESS BY INDEX ROWID | USER_ROLE | 1 | 30 | 3 (0)| 00:00:01 | | |
|* 15 | INDEX UNIQUE SCAN | U_USER_ROLE_IDX1 | 1 | | 2 (0)| 00:00:01 | | |
| 16 | REMOTE | MV_P113PT_USER_HUB | 1 | 7 | 0 (0)| 00:00:01 | HWVAU~ | R->S |
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("A"."ROLE_ID"(+)="ROLE"."ROLE_ID")
4 - access("ROLE"."GRP_ID"=3)
8 - filter( EXISTS (SELECT 0 FROM "P181"."USER_ROLE" "USER_ROLE" WHERE "USER_ROLE"."STTS_ID"=:B1 AND
(TO_NUMBER("USER_ROLE"."ACTV_CD")=1 OR (TO_NUMBER("USER_ROLE"."ACTV_CD")=0 OR TO_NUMBER("USER_ROLE"."ACTV_CD")=3)
AND "USER_ROLE"."EFCTV_TO_DTTM">=SYSDATE@! AND "USER_ROLE"."EFCTV_FROM_DTTM"<=SYSDATE@!)))
10 - access("USER_ROLE"."ROLE_ID"="ROLE"."ROLE_ID")
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------
12 - access("ROLE"."GRP_ID"=3)
13 - filter("USER_ROLE"."PRTPT_CD" IS NOT NULL)
14 - filter(TO_NUMBER("USER_ROLE"."ACTV_CD")=1 OR (TO_NUMBER("USER_ROLE"."ACTV_CD")=0 OR
TO_NUMBER("USER_ROLE"."ACTV_CD")=3) AND "USER_ROLE"."EFCTV_TO_DTTM">=SYSDATE@! AND
"USER_ROLE"."EFCTV_FROM_DTTM"<=SYSDATE@!)
15 - access("USER_ROLE"."STTS_ID"=:B1)
我没有足够的tkprof
答案 0 :(得分:0)
以下查询是否会产生相同的结果?
SELECT c.role_id
, c.subgroup
, c.subgroup_description
, COUNT(a.USER_ID) user_count
FROM cmp_role c
LEFT OUTER JOIN (
SELECT r.user_id
, r.role_id
FROM (
SELECT r.user_id
, r.role_id
, r.participant_code
, MAX(r.status_id)
FROM user_role r
INNER JOIN cmp_role c ON c.role_id = r.role_id
WHERE r.participant_code IS NOT NULL
AND c.group_id = 3
GROUP BY
r.user_id
, r.role_id
, r.participant_code
HAVING MAX(r.status_id) IN (
SELECT status_id
FROM user_role
WHERE (Active = 1
OR (Active IN ( 0,3 )
AND SYSDATE BETWEEN effective_from_date AND effective_to_date)
)
)
) r
INNER JOIN user e ON e.user_id = RTRIM(r.user_id)
) a ON a.role_id = c.role_id
WHERE c.group_id = 3
GROUP BY
c.role_id
, c.subgroup
, c.subgroup_description
ORDER BY
c.subgroup
更容易阅读(对我而言)。如果它产生相同的结果,您可以从内部选择中删除r.participant_code
和MAX(r.status_id)
开始。