*相关表已经脱敏处理
SELECT tmp.PARTY_ID,
s.TICKER_SYMBOL,
tmp.SHAREHOLDER_NAME,
tmp.END_DATE_NEW,
tmp.SHARE_NUM_NEW,
tmp.END_DATE_LAST,
tmp.SHARE_NUM_LAST,
tmp.PROPORTION,
tmp.CHANGE_DIRECTION
FROM (SELECT DISTINCT q.PARTY_ID,
q.SHAREHOLDER_NAME,
q.END_DATE_NEW,
q.SHARE_NUM_NEW,
q.END_DATE_LAST,
q.SHARE_NUM_LAST,
CASE
WHEN q.PROPORTION IS NULL THEN
s.PROPORTION
ELSE
q.PROPORTION
END PROPORTION,
CASE
WHEN s.CHANGE_DIRECTION IS NULL THEN
q.CHANGE_DIRECTION
ELSE
s.CHANGE_DIRECTION
END CHANGE_DIRECTION
FROM (SELECT m.PARTY_ID,
m.END_DATE_NEW,
m.SHAREHOLDER_NAME,
m.SHARE_NUM_NEW,
m.END_DATE_LAST,
m.SHARE_NUM_LAST,
n.PROPORTION,
CASE
WHEN abs(m.SHARE_NUM_NEW -
m.SHARE_NUM_LAST * (1 + n.PROPORTION)) < 0.01 THEN
'不变'
WHEN m.SHARE_NUM_NEW -
m.SHARE_NUM_LAST * (1 + n.PROPORTION) >= 0.01 THEN
'增持'
ELSE
'减持'
END CHANGE_DIRECTION
FROM (SELECT a.PARTY_ID PARTY_ID,
a.END_DATE END_DATE_NEW,
a.SHAREHOLDER_NAME SHAREHOLDER_NAME,
a.SHARE_NUM SHARE_NUM_NEW,
b.END_DATE END_DATE_LAST,
b.SHARE_NUM SHARE_NUM_LAST
FROM (SELECT *
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')) a,
(SELECT *
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')) b
WHERE a.PARTY_ID = b.PARTY_ID
AND a.SHAREHOLDER_NAME = b.SHAREHOLDER_NAME
AND b.END_DATE =
(SELECT MAX(END_DATE)
FROM (SELECT *
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME =
'中国证券金融股份有限公司')) c
WHERE c.PARTY_ID = a.PARTY_ID
AND c.SHAREHOLDER_NAME = a.SHAREHOLDER_NAME
AND c.END_DATE < a.END_DATE)
UNION
SELECT PARTY_ID PARTY_ID,
END_DATE END_DATE_NEW,
SHAREHOLDER_NAME SHAREHOLDER_NAME,
SHARE_NUM SHARE_NUM_NEW,
NULL END_DATE_LAST,
NULL SHARE_NUM_LAST
FROM testtable1 a,
(SELECT PARTY_ID dm,
MIN(END_DATE) zxrq,
SHAREHOLDER_NAME gdmc
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')
GROUP BY PARTY_ID, SHAREHOLDER_NAME) b
WHERE a.PARTY_ID = b.dm
AND a.END_DATE = b.zxrq
AND a.SHAREHOLDER_NAME = b.gdmc) m,
(SELECT b.PARTY_ID PARTY_ID,
a.LIST_DATE 除权日,
a.ALLOTMENT_RATIO PROPORTION
FROM equ_allot a, testtable3 b
WHERE a.SECURITY_ID = b.SECURITY_ID
AND b.TRANS_CURR_CD = 'CNY'
AND a.ALLOTMENT_RATIO IS NOT NULL
AND a.LIST_DATE IS NOT NULL
UNION
SELECT b.PARTY_ID PARTY_ID,
a.EX_DIV_DATE 除权日,
(CASE
WHEN a.PER_SHARE_DIV_RATIO IS NULL THEN
0
ELSE
a.PER_SHARE_DIV_RATIO
END) + (CASE
WHEN a.PER_SHARE_TRANS_RATIO IS NULL THEN
0
ELSE
a.PER_SHARE_TRANS_RATIO
END) PROPORTION
FROM testtable2 a, testtable3 b
WHERE a.EVENT_PROCESS_CD = '6'
AND a.IS_DIV IN ('05', '09', '15')
AND a.SECURITY_ID = b.SECURITY_ID
AND b.TRANS_CURR_CD = 'CNY'
AND (a.PER_SHARE_DIV_RATIO IS NOT NULL OR
a.PER_SHARE_TRANS_RATIO IS NOT NULL)) n
WHERE m.PARTY_ID = n.PARTY_ID
AND n.除权日 BETWEEN m.END_DATE_LAST AND m.END_DATE_NEW) s
RIGHT JOIN (SELECT a.PARTY_ID PARTY_ID,
a.END_DATE END_DATE_NEW,
a.SHAREHOLDER_NAME SHAREHOLDER_NAME,
a.SHARE_NUM SHARE_NUM_NEW,
b.END_DATE END_DATE_LAST,
b.SHARE_NUM SHARE_NUM_LAST,
NULL PROPORTION,
CASE
WHEN abs(a.SHARE_NUM - b.SHARE_NUM) < 0.01 THEN
'不变'
WHEN a.SHARE_NUM - b.SHARE_NUM >= 0.01 THEN
'增持'
ELSE
'减持'
END CHANGE_DIRECTION
FROM (SELECT *
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')) a,
(SELECT *
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')) b
WHERE a.PARTY_ID = b.PARTY_ID
AND a.SHAREHOLDER_NAME = b.SHAREHOLDER_NAME
AND b.END_DATE =
(SELECT MAX(END_DATE)
FROM (SELECT *
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')) c
WHERE c.PARTY_ID = a.PARTY_ID
AND c.SHAREHOLDER_NAME = a.SHAREHOLDER_NAME
AND c.END_DATE < a.END_DATE)
UNION
SELECT PARTY_ID PARTY_ID,
END_DATE END_DATE_NEW,
SHAREHOLDER_NAME SHAREHOLDER_NAME,
SHARE_NUM SHARE_NUM_NEW,
NULL END_DATE_LAST,
NULL SHARE_NUM_LAST,
NULL PROPORTION,
'新进' CHANGE_DIRECTION
FROM testtable1 a,
(SELECT PARTY_ID dm,
MIN(END_DATE) zxrq,
SHAREHOLDER_NAME gdmc
FROM testtable1
WHERE (END_DATE LIKE '%-03-31%' OR
END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR
END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR
SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')
GROUP BY PARTY_ID, SHAREHOLDER_NAME) b
WHERE a.PARTY_ID = b.dm
AND a.END_DATE = b.zxrq
AND a.SHAREHOLDER_NAME = b.gdmc) q
ON s.PARTY_ID = q.PARTY_ID
AND s.END_DATE_NEW = q.END_DATE_NEW
AND s.SHAREHOLDER_NAME = q.SHAREHOLDER_NAME) tmp,
testtable3 s
WHERE tmp.PARTY_ID = s.PARTY_ID
and s.ASSET_CLASS = 'e'
and s.EXCHANGE_CD IN ('XSHE', 'XSHG')
and s.TRANS_CURR_CD = 'CNY'
and s.DY_USE_FLG = '1'
and s.TICKER_SYMBOL not like '003%'
and s.TICKER_SYMBOL not like '14%'
and s.TICKER_SYMBOL not like '36%'
and s.TICKER_SYMBOL <> '600849'
ORDER BY tmp.PARTY_ID, tmp.END_DATE_NEW
主要把共同部分的SQL找出来了,因为mysql不支持with子句的用法,先做成了一个视图。
-- 创建子视图
use backup;
create view testbzm as
SELECT *
FROM datayesdb.testtable1
WHERE (END_DATE LIKE '%-03-31%' OR END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')
-- 执行查询
SELECT tmp.PARTY_ID,
s.TICKER_SYMBOL,
tmp.SHAREHOLDER_NAME,
tmp.END_DATE_NEW,
tmp.SHARE_NUM_NEW,
tmp.END_DATE_LAST,
tmp.SHARE_NUM_LAST,
tmp.PROPORTION,
tmp.CHANGE_DIRECTION
FROM (SELECT DISTINCT q.PARTY_ID,
q.SHAREHOLDER_NAME,
q.END_DATE_NEW,
q.SHARE_NUM_NEW,
q.END_DATE_LAST,
q.SHARE_NUM_LAST,
CASE
WHEN q.PROPORTION IS NULL THEN
s.PROPORTION
ELSE
q.PROPORTION
END PROPORTION,
CASE
WHEN s.CHANGE_DIRECTION IS NULL THEN
q.CHANGE_DIRECTION
ELSE
s.CHANGE_DIRECTION
END CHANGE_DIRECTION
FROM (SELECT m.PARTY_ID,
m.END_DATE_NEW,
m.SHAREHOLDER_NAME,
m.SHARE_NUM_NEW,
m.END_DATE_LAST,
m.SHARE_NUM_LAST,
n.PROPORTION,
CASE
WHEN abs(m.SHARE_NUM_NEW -
m.SHARE_NUM_LAST * (1 + n.PROPORTION)) < 0.01 THEN
'不变'
WHEN m.SHARE_NUM_NEW -
m.SHARE_NUM_LAST * (1 + n.PROPORTION) >= 0.01 THEN
'增持'
ELSE
'减持'
END CHANGE_DIRECTION
FROM (SELECT a.PARTY_ID PARTY_ID,
a.END_DATE END_DATE_NEW,
a.SHAREHOLDER_NAME SHAREHOLDER_NAME,
a.SHARE_NUM SHARE_NUM_NEW,
b.END_DATE END_DATE_LAST,
b.SHARE_NUM SHARE_NUM_LAST
FROM backup.testbzm a, backup.testbzm b
WHERE a.PARTY_ID = b.PARTY_ID
AND a.SHAREHOLDER_NAME = b.SHAREHOLDER_NAME
AND b.END_DATE =
(SELECT MAX(END_DATE)
FROM backup.testbzm c
WHERE c.PARTY_ID = a.PARTY_ID
AND c.SHAREHOLDER_NAME = a.SHAREHOLDER_NAME
AND c.END_DATE < a.END_DATE)
UNION
SELECT PARTY_ID PARTY_ID,
END_DATE END_DATE_NEW,
SHAREHOLDER_NAME SHAREHOLDER_NAME,
SHARE_NUM SHARE_NUM_NEW,
NULL END_DATE_LAST,
NULL SHARE_NUM_LAST
FROM testtable1 a,
(SELECT PARTY_ID dm,
MIN(END_DATE) zxrq,
SHAREHOLDER_NAME gdmc
FROM backup.testbzm
GROUP BY PARTY_ID, SHAREHOLDER_NAME) b
WHERE a.PARTY_ID = b.dm
AND a.END_DATE = b.zxrq
AND a.SHAREHOLDER_NAME = b.gdmc) m,
(SELECT b.PARTY_ID PARTY_ID,
a.LIST_DATE 除权日,
a.ALLOTMENT_RATIO PROPORTION
FROM equ_allot a, testtable3 b
WHERE a.SECURITY_ID = b.SECURITY_ID
AND b.TRANS_CURR_CD = 'CNY'
AND a.ALLOTMENT_RATIO IS NOT NULL
AND a.LIST_DATE IS NOT NULL
UNION
SELECT b.PARTY_ID PARTY_ID,
a.EX_DIV_DATE 除权日,
(CASE
WHEN a.PER_SHARE_DIV_RATIO IS NULL THEN
0
ELSE
a.PER_SHARE_DIV_RATIO
END) + (CASE
WHEN a.PER_SHARE_TRANS_RATIO IS NULL THEN
0
ELSE
a.PER_SHARE_TRANS_RATIO
END) PROPORTION
FROM testtable2 a, testtable3 b
WHERE a.EVENT_PROCESS_CD = '6'
AND a.IS_DIV IN ('05', '09', '15')
AND a.SECURITY_ID = b.SECURITY_ID
AND b.TRANS_CURR_CD = 'CNY'
AND (a.PER_SHARE_DIV_RATIO IS NOT NULL OR
a.PER_SHARE_TRANS_RATIO IS NOT NULL)) n
WHERE m.PARTY_ID = n.PARTY_ID
AND n.除权日 BETWEEN m.END_DATE_LAST AND m.END_DATE_NEW) s
RIGHT JOIN (SELECT a.PARTY_ID PARTY_ID,
a.END_DATE END_DATE_NEW,
a.SHAREHOLDER_NAME SHAREHOLDER_NAME,
a.SHARE_NUM SHARE_NUM_NEW,
b.END_DATE END_DATE_LAST,
b.SHARE_NUM SHARE_NUM_LAST,
NULL PROPORTION,
CASE
WHEN abs(a.SHARE_NUM - b.SHARE_NUM) < 0.01 THEN
'不变'
WHEN a.SHARE_NUM - b.SHARE_NUM >= 0.01 THEN
'增持'
ELSE
'减持'
END CHANGE_DIRECTION
FROM backup.testbzm a, backup.testbzm b
WHERE a.PARTY_ID = b.PARTY_ID
AND a.SHAREHOLDER_NAME = b.SHAREHOLDER_NAME
AND b.END_DATE =
(SELECT MAX(END_DATE)
FROM backup.testbzm c
WHERE c.PARTY_ID = a.PARTY_ID
AND c.SHAREHOLDER_NAME = a.SHAREHOLDER_NAME
AND c.END_DATE < a.END_DATE)
UNION
SELECT PARTY_ID PARTY_ID,
END_DATE END_DATE_NEW,
SHAREHOLDER_NAME SHAREHOLDER_NAME,
SHARE_NUM SHARE_NUM_NEW,
NULL END_DATE_LAST,
NULL SHARE_NUM_LAST,
NULL PROPORTION,
'新进' CHANGE_DIRECTION
FROM testtable1 a,
(SELECT PARTY_ID dm,
MIN(END_DATE) zxrq,
SHAREHOLDER_NAME gdmc
FROM backup.testbzm
GROUP BY PARTY_ID, SHAREHOLDER_NAME) b
WHERE a.PARTY_ID = b.dm
AND a.END_DATE = b.zxrq
AND a.SHAREHOLDER_NAME = b.gdmc) q
ON s.PARTY_ID = q.PARTY_ID
AND s.END_DATE_NEW = q.END_DATE_NEW
AND s.SHAREHOLDER_NAME = q.SHAREHOLDER_NAME) tmp,
testtable3 s
WHERE tmp.PARTY_ID = s.PARTY_ID
and s.ASSET_CLASS = 'e'
and s.EXCHANGE_CD IN ('XSHE', 'XSHG')
and s.TRANS_CURR_CD = 'CNY'
and s.DY_USE_FLG = '1'
and s.TICKER_SYMBOL not like '003%'
and s.TICKER_SYMBOL not like '14%'
and s.TICKER_SYMBOL not like '36%'
and s.TICKER_SYMBOL <> '600849'
ORDER BY tmp.PARTY_ID, tmp.END_DATE_NEW
经过第二步之后差不多能看了,但是仔细看业务还是又可以合并的内容,结合和业务人员的沟通最终优化如下:
-- 创建子视图
use backup;
create view testbzm as
SELECT *
FROM datayesdb.testtable1
WHERE (END_DATE LIKE '%-03-31%' OR END_DATE LIKE '%-06-30' OR
END_DATE LIKE '%-09-30' OR END_DATE LIKE '%-12-31')
AND (SHAREHOLDER_NAME LIKE '%证金%' OR SHAREHOLDER_NAME LIKE '%汇金%' OR
SHAREHOLDER_NAME = '中国证券金融股份有限公司')
use backup;
create view chuquanpg as
SELECT -- 除权日期和配股比例
b.PARTY_ID PARTY_ID, a.LIST_DATE cqr, a.ALLOTMENT_RATIO PROPORTION
FROM datayesdb.equ_allot a, datayesdb.testtable3 b
WHERE a.SECURITY_ID = b.SECURITY_ID
AND b.TRANS_CURR_CD = 'CNY'
AND a.ALLOTMENT_RATIO IS NOT NULL
AND a.LIST_DATE IS NOT NULL
and a.EQU_TYPE_CD = '0201010201' -- 核实增加条件
UNION
SELECT -- 分红除权日期,分红的送转比
b.PARTY_ID PARTY_ID,
a.EX_DIV_DATE cqr,
(CASE
WHEN a.PER_SHARE_DIV_RATIO IS NULL THEN
0
ELSE
a.PER_SHARE_DIV_RATIO
END) + (CASE
WHEN a.PER_SHARE_TRANS_RATIO IS NULL THEN
0
ELSE
a.PER_SHARE_TRANS_RATIO
END) PROPORTION
FROM datayesdb.testtable2 a, datayesdb.testtable3 b
WHERE a.EVENT_PROCESS_CD = '6'
AND a.IS_DIV IN ('05', '09', '15')
AND a.SECURITY_ID = b.SECURITY_ID
AND b.TRANS_CURR_CD = 'CNY'
AND (a.PER_SHARE_DIV_RATIO IS NOT NULL OR
a.PER_SHARE_TRANS_RATIO IS NOT NULL)
-- 执行查询
SELECT tmp.PARTY_ID,
s.TICKER_SYMBOL,
tmp.SHAREHOLDER_NAME,
tmp.END_DATE_NEW,
tmp.SHARE_NUM_NEW,
tmp.END_DATE_LAST,
tmp.SHARE_NUM_LAST,
tmp.PROPORTION,
tmp.CHANGE_DIRECTION
FROM (SELECT a.PARTY_ID PARTY_ID,
a.END_DATE END_DATE_NEW,
a.SHAREHOLDER_NAME SHAREHOLDER_NAME,
a.SHARE_NUM SHARE_NUM_NEW,
b.END_DATE END_DATE_LAST,
b.SHARE_NUM SHARE_NUM_LAST,
(SELECT PROPORTION
FROM backup.chuquanpg z
WHERE z.PARTY_ID = a.PARTY_ID
AND z.cqr BETWEEN b.END_DATE AND a.END_DATE LIMIT 1) PROPORTION,
CASE
WHEN abs(a.SHARE_NUM - b.SHARE_NUM) < 0.01 THEN
'不变'
WHEN a.SHARE_NUM - b.SHARE_NUM >= 0.01 THEN
'增持'
ELSE
'减持'
END CHANGE_DIRECTION
FROM backup.testbzm a, backup.testbzm b
WHERE a.PARTY_ID = b.PARTY_ID
AND a.SHAREHOLDER_NAME = b.SHAREHOLDER_NAME
AND b.END_DATE = (SELECT MAX(END_DATE)
FROM backup.testbzm c
WHERE c.PARTY_ID = a.PARTY_ID
AND c.SHAREHOLDER_NAME = a.SHAREHOLDER_NAME
AND c.END_DATE < a.END_DATE)
UNION ALL
SELECT PARTY_ID PARTY_ID,
END_DATE END_DATE_NEW,
SHAREHOLDER_NAME SHAREHOLDER_NAME,
SHARE_NUM SHARE_NUM_NEW,
NULL END_DATE_LAST,
NULL SHARE_NUM_LAST,
NULL PROPORTION,
'新进' CHANGE_DIRECTION
FROM testtable1 a,
(SELECT PARTY_ID dm, MIN(END_DATE) zxrq, SHAREHOLDER_NAME gdmc
FROM backup.testbzm
GROUP BY PARTY_ID, SHAREHOLDER_NAME) b
WHERE a.PARTY_ID = b.dm
AND a.END_DATE = b.zxrq
AND a.SHAREHOLDER_NAME = b.gdmc) tmp,
testtable3 s
WHERE tmp.PARTY_ID = s.PARTY_ID
and s.ASSET_CLASS = 'e'
and s.EXCHANGE_CD IN ('XSHE', 'XSHG')
and s.TRANS_CURR_CD = 'CNY'
and s.DY_USE_FLG = '1'
and s.TICKER_SYMBOL not like '003%'
and s.TICKER_SYMBOL not like '14%'
and s.TICKER_SYMBOL not like '36%'
and s.TICKER_SYMBOL <> '600849'
ORDER BY tmp.PARTY_ID, tmp.END_DATE_NEW
小结:
1. 遇到很复杂的SQL(特别是没有任何备注的),最快的处理方法是拉业务人员过来沟通。
2. SQL分解看逻辑,然后逐步理解整个逻辑。
3. mysql的执行计划中,视图是作为设备插入的,类似于临时表,本案例因为最终要提供视图给API来调用,所以必须拆分子视图(mysql视图不支持子查询,只能拆成子视图),这样正好提高了系统的效率(原SQL执行计划走乱,效率很差)