我正在尝试获取以下查询的输出。它要永远做,没有输出。您能帮忙优化查询吗?我尝试使用提示并行,但仍然没有输出。 TabA大约有120万条记录,TabB大约有70万条记录。数据库是Oracle。
WITH TAB1 as (
SELECT
P_TXN_ID,PROD_CD,P_TYPE1,P_TYPE2,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='FBO' AND LAST_UPD_DT='20-NOV-17' ) FBO,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='ORG' AND LAST_UPD_DT='20-NOV-17' ) ORG,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='SEND' AND LAST_UPD_DT='20-NOV-17' ) SEND,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='RCV' AND LAST_UPD_DT='20-NOV-17' ) RCV,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='SCND' AND LAST_UPD_DT='20-NOV-17' ) SCND,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='BENE' AND LAST_UPD_DT='20-NOV-17' ) BENE,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='INT1' AND LAST_UPD_DT='20-NOV-17' ) INT1,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='INT2' AND LAST_UPD_DT='20-NOV-17' ) INT2,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='INT3' AND LAST_UPD_DT='20-NOV-17' ) INT3,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='INT4' AND LAST_UPD_DT='20-NOV-17' ) INT4,
(SELECT COALESCE(FT.V_PARTY_ID_TYPE,'XX') FROM TabA FT WHERE FT.P_TXN_ID=ST.P_TXN_ID AND FT.P_ROLE='INT5' AND LAST_UPD_DT='20-NOV-17' ) INT5
FROM
(SELECT PROD_CD,P_TYPE1,P_TYPE2,LAST_UPD_DT,P_TXN_ID
FROM TabB
) ST
WHERE LAST_UPD_DT>='20-NOV-17' AND LAST_UPD_DT<='22-NOV-17'
)
SELECT /*+ parallel(100)*/
COUNT(*),
PROD_CD,
P_TYPE1,
FBO,ORG,SEND,RCV,SCND,BENE,
INT1,INT2,INT3,INT4,INT5
FROM
TAB1
GROUP BY PROD_CD,
P_TYPE1,
FBO,ORG,SEND,RCV,SCND,BENE,
INT1,INT2,INT3,INT4,INT5
ORDER BY PROD_CD;
先谢谢了。为了使事情变得简单,下面是上面查询试图实现的示例。假设表TXN
中包含以下数据:
TXN
Col1 Col2 Col3 Type
1 AA abc FBO
2 null abc FBO
3 BB abc ORG
4 CC def ORG
5 DD def ORG
6 EE pqr SCND
7 EE pqr SCND
8 CC def RCV
然后查询的输出将是:
Col2 Col3 FBO ORG SCND RCV
AA abc 1 0 0 0
null abc 1 0 0 0
BB abc 1 0 0 0
CC def 0 1 0 1
DD def 0 1 0 0
EE pqr 0 0 2 0
答案 0 :(得分:1)
我发现很难遵循您的代码和您的解释。但是,我很确定条件聚合就是您所需要的。
类似这样的东西:
SELECT b.PROD_CD, b.P_TYPE1, b.P_TYPE2,
MAX(CASE WHEN FT.P_ROLE = 'FBO' THEN a.V_PARTY_ID_TYPE END) as FBO,
MAX(CASE WHEN FT.P_ROLE = 'ORG' THEN a.V_PARTY_ID_TYPE END) as ORG,
MAX(CASE WHEN FT.P_ROLE = 'SEND' THEN a.V_PARTY_ID_TYPE END) as SEND,
MAX(CASE WHEN FT.P_ROLE = 'RCV' THEN a.V_PARTY_ID_TYPE END) as RCV,
MAX(CASE WHEN FT.P_ROLE = 'SCND' THEN a.V_PARTY_ID_TYPE END) as SCND,
MAX(CASE WHEN FT.P_ROLE = 'BENE' THEN a.V_PARTY_ID_TYPE END) as BENE,
MAX(CASE WHEN FT.P_ROLE = 'FBO' THEN a.V_PARTY_ID_TYPE END) as FBO,
MAX(CASE WHEN FT.P_ROLE = 'INT1' THEN a.V_PARTY_ID_TYPE END) as INT1,
MAX(CASE WHEN FT.P_ROLE = 'INT2' THEN a.V_PARTY_ID_TYPE END) as INT2,
MAX(CASE WHEN FT.P_ROLE = 'INT3' THEN a.V_PARTY_ID_TYPE END) as INT3,
MAX(CASE WHEN FT.P_ROLE = 'INT4' THEN a.V_PARTY_ID_TYPE END) as INT4
MAX(CASE WHEN FT.P_ROLE = 'INT5' THEN a.V_PARTY_ID_TYPE END) as INT5
FROM TabB b JOIN
TabA a
ON a.P_TXN_ID = b.P_TXN_ID AND
a.LAST_UPD_DT = DATE '2017-11-20'
WHERE LAST_UPD_DT >= DATE '2017-11-20' AND LAST_UPD_DT <= DATE '2017-11-22'
GROUP BY PROD_CD, P_TYPE1, P_TYPE2;
答案 1 :(得分:0)
答案 2 :(得分:0)
您没有发布执行计划,因此只能进行基于猜测的推荐。
以下是检查清单:
1)表TABA
未建立索引-显然导致大量FULL TABLE SCAN
2)表TABA
的索引编入不正确-例如由于P_TXN_ID丢失或
仅索引P_TXN_ID列,并且您必须先扫描大量数字或行,然后才能匹配角色和日期
3)表TABA
已正确索引,即在P_TXN_ID,P_ROLE,LAST_UPD_DT上,但您在TABB
中处理了大量行
要处理TABB
中的100K行的示例,您需要100K * 11 = 1.1M(您的子查询数)index access
。对于在磁盘上带有索引的大表,您每秒获得的行数不会超过100。所以
您最好摆脱它,对表执行哈希联接。
最后但并非最不重要的-您采用平行运动的方法类似于轮胎空了并且油门全开的情况。
答案 3 :(得分:0)
要解决要得出的样本数据,您只需要“条件聚合”,基本上这意味着对查询count(case when ... then 1 end)
的操作如下:
SELECT
col2
, col3
, COUNT( CASE WHEN type = 'FBO' THEN 1 END ) AS FBO
, COUNT( CASE WHEN type = 'ORG' THEN 1 END ) AS ORG
, COUNT( CASE WHEN type = 'SCND' THEN 1 END ) AS SCND
, COUNT( CASE WHEN type = 'RCV' THEN 1 END ) AS RCV
FROM txn
GROUP BY
col2
, col3
ORDER BY
col2
, col3
结果是:
+----+------+------+-----+-----+------+-----+
| | COL2 | COL3 | FBO | ORG | SCND | RCV |
+----+------+------+-----+-----+------+-----+
| 1 | AA | abc | 1 | 0 | 0 | 0 |
| 2 | BB | abc | 0 | 1 | 0 | 0 |
| 3 | CC | def | 0 | 1 | 0 | 1 |
| 4 | DD | def | 0 | 1 | 0 | 0 |
| 5 | EE | pqr | 0 | 0 | 2 | 0 |
| 6 | NULL | abc | 1 | 0 | 0 | 0 |
+----+------+------+-----+-----+------+-----+
所以您可以这样做:
SELECT
b.PROD_CD
, b.P_TYPE1
, b.P_TYPE2
, COUNT( CASE WHEN FT.P_ROLE = 'FBO' THEN a.V_PARTY_ID_TYPE END ) AS FBO
, COUNT( CASE WHEN FT.P_ROLE = 'ORG' THEN a.V_PARTY_ID_TYPE END ) AS ORG
, COUNT( CASE WHEN FT.P_ROLE = 'SEND' THEN a.V_PARTY_ID_TYPE END ) AS SEND
, COUNT( CASE WHEN FT.P_ROLE = 'RCV' THEN a.V_PARTY_ID_TYPE END ) AS RCV
, COUNT( CASE WHEN FT.P_ROLE = 'SCND' THEN a.V_PARTY_ID_TYPE END ) AS SCND
, COUNT( CASE WHEN FT.P_ROLE = 'BENE' THEN a.V_PARTY_ID_TYPE END ) AS BENE
, COUNT( CASE WHEN FT.P_ROLE = 'FBO' THEN a.V_PARTY_ID_TYPE END ) AS FBO
, COUNT( CASE WHEN FT.P_ROLE = 'INT1' THEN a.V_PARTY_ID_TYPE END ) AS INT1
, COUNT( CASE WHEN FT.P_ROLE = 'INT2' THEN a.V_PARTY_ID_TYPE END ) AS INT2
, COUNT( CASE WHEN FT.P_ROLE = 'INT3' THEN a.V_PARTY_ID_TYPE END ) AS INT3
, COUNT( CASE WHEN FT.P_ROLE = 'INT4' THEN a.V_PARTY_ID_TYPE END ) AS INT4
, COUNT( CASE WHEN FT.P_ROLE = 'INT5' THEN a.V_PARTY_ID_TYPE END ) AS INT5
FROM TabB b
JOIN TabA a ON a.P_TXN_ID = b.P_TXN_ID
AND a.LAST_UPD_DT = DATE '2017-11-20'
WHERE LAST_UPD_DT >= DATE '2017-11-20' AND LAST_UPD_DT <= DATE '2017-11-22'
GROUP BY
PROD_CD
, P_TYPE1
, P_TYPE2;
但是请注意,如果a.V_PARTY_ID_TYPE
为NULL,则计数将不会增加1。