要调整的查询如下。
查询的输入为year_Month='201507'
SELECT A.account_number,
A.market,
A.security_type,
A.total_market_value,
A.max_event_Date,
-- first inner Query
(SELECT COUNT(*)
FROM MIGC_ACCOUNT_STATEMENT acctStmt
WHERE acctStmt.account_number =A.account_number
AND acctStmt.market =A.market
AND acctStmt.security_type =A.security_type
AND acctStmt.year_Month =A.year_Month
AND acctStmt.ACCOUNT_EVENT_DATE = A.max_event_Date
) AS isincount,
-- second inner Query
(SELECT COUNT(COUNT(*))
FROM MIGC_ACCOUNT_STATEMENT acctStmt
WHERE acctStmt.account_number =A.account_number
AND acctStmt.market =A.market
AND(( acctStmt.security_type =A.security_type)
OR (acctStmt.security_type IS NULL))
AND acctStmt.year_Month =A.year_Month
GROUP BY acctStmt.ACCOUNT_EVENT_DATE
) AS totalcount,
-- 3rd inner Query
(SELECT COUNT(*)
FROM MIGC_ACCOUNT_STATEMENT acctStmt
WHERE acctStmt.account_number =A.account_number
AND acctStmt.market =A.market
AND acctStmt.security_type =A.security_type
AND acctStmt.year_Month =A.year_Month
AND acctStmt.ACCOUNT_EVENT_DATE = A.max_event_Date
AND acctStmt.market_value = 0
) AS zero_market_value,
-- 4th inner Query
(SELECT SUM(acctStmt.market_value)
FROM MIGC_ACCOUNT_STATEMENT acctStmt
WHERE acctStmt.account_number =A.account_number
AND acctStmt.market =A.market
AND acctStmt.security_type =A.security_type
AND acctStmt.ACCOUNT_EVENT_DATE =A.max_event_Date
AND acctStmt.year_Month =A.year_Month
GROUP BY acctStmt.account_number,
acctStmt.security_type,
acctStmt.market
) AS mon_end_value
FROM
--inner view
(SELECT account_number,
market,
security_type,
SUM(market_value) AS total_market_value,
MAX(ACCOUNT_EVENT_DATE) AS max_event_Date,
year_Month
FROM MIGC_ACCOUNT_STATEMENT
WHERE year_Month ='201507'
AND security_Type IS NOT NULL
GROUP BY account_number,
market,
security_type,
year_Month
) A
我的表格结构如下
CREATE TABLE MIGC_ACCOUNT_STATEMENT"
(
"ID" VARCHAR2(15 CHAR) NOT NULL ENABLE,
"REQUEST_ID" VARCHAR2(100 CHAR),
"REQUEST_DATE" TIMESTAMP (6),
"PRODUCT_GROUP" VARCHAR2(50 CHAR),
"SOURCE_SYSTEM" VARCHAR2(3 CHAR),
"PROCESSED_BY_SITE" VARCHAR2(50 CHAR),
"ACCOUNT_EVENT_DATE" DATE,
"ACCOUNT_NUMBER" VARCHAR2(50 CHAR),
"SECURITY_ID" VARCHAR2(50 CHAR),
"SECURITY_TYPE" VARCHAR2(100 CHAR),
"SECURITY_NAME" VARCHAR2(200 CHAR),
"SECURITY_PRICE" NUMBER,
"SECURITY_PRICE_DATE" DATE,
"QUANTITY" NUMBER,
"MARKET_VALUE_CURRENCY" VARCHAR2(5 CHAR),
"MARKET" VARCHAR2(100 CHAR),
"MARKET_VALUE" NUMBER,
"SECURITY_ID_TYPE" VARCHAR2(50 CHAR),
"LOB_ID" VARCHAR2(20 CHAR),
"YEAR_MONTH" NUMBER,
"BATCH_NUMBER" NUMBER NOT NULL ENABLE,
"CUSTOMER_ID" VARCHAR2(50 CHAR)
)
和Id
是主键。我检查了查询成本,它非常高。
答案 0 :(得分:1)
评论太长了。
首先,您应该将用于关联的所有列索引 - 一个索引,使用复合键。所以:MIGC_ACCOUNT_STATEMENT(account_number, acctStmt.market, security_type, year_Month, ACCOUNT_EVENT_DAT)
是第一个的最佳索引。
其次,请勿使用COUNT(COUNT(*))
。我的猜测是,即使是真正理解该构造的Oracle爱好者仍然会发现COUNT(DISTINCT acctStmt.ACCOUNT_EVENT_DATE)
更清楚。 (注意:这些不完全相同,因为您的版本计算NULL
。我猜不会发生这种情况。)
答案 1 :(得分:0)
我认为你可以通过使用条件分析函数来避免同一个表的多个表查找,如下所示:
SELECT account_number,
market,
security_type,
SUM(CASE WHEN a.security_type is not NULL THEN market_value END) AS total_market_value,
isincount,
totalcount,
zero_market_value,
mon_end_value
FROM (SELECT a.account_number,
a.market,
a.security_type,
a.max_event_date,
COUNT(CASE WHEN a.security_type is not NULL
AND a.account_event_date = max_event_date THEN ID END)
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS isincount,
COUNT(DISTINCT NVL(a.account_event_date, DATE '1800-01-01'))
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS totalcount,
COUNT(CASE WHEN a.security_type is not NULL
AND a.account_event_date = max_event_date
AND a.market_value = 0 THEN ID END)
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS zero_market_value,
SUM(CASE WHEN a.security_type is not NULL
AND a.account_event_date = max_event_date THEN a.market_value END)
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS mon_end_value
FROM --inner view
(SELECT id,
account_number,
market,
security_type,
market_value,
MAX(account_event_date) OVER (PARTITION BY BY account_number, market, security_type, year_month) AS max_event_date,
year_month
FROM migc_account_statement
WHERE year_month = 201507)) a
GROUP BY account_number,
market,
security_type,
isincount,
totalcount,
zero_market_value,
mon_end_value;
为了便于阅读,我建议使用子查询因子(又名with子句,又名Common Table Expressions又称CTE),所以它看起来像:
WITH results_with_max_dt AS (SELECT id,
account_number,
market,
security_type,
market_value,
MAX(account_event_date) OVER (PARTITION BY BY account_number, market, security_type, year_month) AS max_event_date,
year_month
FROM migc_account_statement
WHERE year_month = 201507),
conditional_values AS (SELECT a.account_number,
a.market,
a.security_type,
a.max_event_date,
COUNT(CASE WHEN a.security_type is not NULL
AND a.account_event_date = max_event_date THEN ID END)
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS isincount,
COUNT(DISTINCT NVL(a.account_event_date, DATE '1800-01-01'))
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS totalcount,
COUNT(CASE WHEN a.security_type is not NULL
AND a.account_event_date = max_event_date
AND a.market_value = 0 THEN ID END)
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS zero_market_value,
SUM(CASE WHEN a.security_type is not NULL
AND a.account_event_date = max_event_date THEN a.market_value END)
OVER (PARTITION BY a.account_number, a.market, a.security_type, a.year_month) AS mon_end_value
FROM results_with_max_dt a)
SELECT account_number,
market,
security_type,
SUM(CASE WHEN a.security_type is not NULL THEN market_value END) AS total_market_value,
isincount,
totalcount,
zero_market_value,
mon_end_value
FROM conditional_values
GROUP BY account_number,
market,
security_type,
isincount,
totalcount,
zero_market_value,
mon_end_value;
N.B。以上查询未经测试。另请注意,我已从201507年左右删除了单引号,因为根据您提供的表格DDL,year_month
列的数据类型为NUMBER
。