2
我有以下包含重複子查詢的巨大查詢,它對我來說看起來效率很低。我如何優化它?如何使用重複子查詢優化龐大查詢
SELECT T2.date1, T2.date2, T2.period, T1.market, T1.ticker, 0 AS scenario
FROM
(SELECT DISTINCT
Q.market AS market,
Q.ticker AS ticker
FROM portfolio.scenario S RIGHT JOIN portfolio.quote Q
ON S.series = (SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1) AND
Q.market = S.market AND
Q.ticker = S.ticker
WHERE Q.date = '2010-07-01' AND
S.date1 IS NULL) AS T1
JOIN
(SELECT DISTINCT S.date1, S.date2, S.period
FROM scenario S
WHERE S.series = (SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1) AND
S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01') AS T2
UNION
SELECT S.date1 AS date1,
S.date2 AS date2,
S.period AS period,
Q.market AS market,
Q.ticker AS ticker,
Q.close * EXP(S.ratio) AS scenario
FROM portfolio.scenario S , portfolio.quote Q
WHERE S.series = (SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1) AND
S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
Q.date = '2010-07-01' AND
Q.market = S.market AND
Q.ticker = S.ticker
UNION
SELECT T2.date1, T2.date2, T2.period, T1.market, T1.ticker, 0 AS scenario
FROM
(SELECT DISTINCT
Q.market AS market,
Q.ticker AS ticker
FROM portfolio.scenario S , portfolio.quote Q
WHERE Q.date = '2010-07-01' AND
Q.market = S.market AND
Q.ticker = S.ticker AND
S.series = (SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1) AND
S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01') AS T1
JOIN
(SELECT DISTINCT S.date1, S.date2, S.period
FROM scenario S
WHERE S.series = (SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1) AND
S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01') AS T2
WHERE (T2.date1, T2.date2, T2.period, T1.market, T1.ticker)
NOT IN (SELECT S.date1 AS date1,
S.date2 AS date2,
S.period AS period,
Q.market AS market,
Q.ticker AS ticker
FROM portfolio.scenario S , portfolio.quote Q
WHERE Q.date = '2010-07-01' AND
Q.market = S.market AND
Q.ticker = S.ticker AND
S.series = (SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1) AND
S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01')
ORDER BY
date1,date2,period,market,ticker
@Bruce的評論和一些邏輯,現在減少一個子查詢我的查詢之後是:
(SELECT S.date1,
S.date2,
S.period,
Q.market,
Q.ticker,
Q.close * EXP(S.ratio) AS scenario
FROM portfolio.scenario S , portfolio.quote Q
WHERE
S.date1 >= (@date1 := '2009-09-01') AND
S.date2 <= (@date2 := '2010-07-01') AND
Q.date = (@qdate := '2010-07-01') AND
S.series =
(@series :=
(SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1)) AND
Q.market = S.market AND
Q.ticker = S.ticker)
UNION
(SELECT T2.date1, T2.date2, T2.period, T1.market, T1.ticker, 0 AS scenario
FROM
(SELECT Q.market, Q.ticker
FROM quote Q
WHERE Q.date = @qdate) AS T1
JOIN
(SELECT DISTINCT S.date1, S.date2, S.period
FROM scenario S
WHERE S.series = @series AND
S.date1 >= @date1 AND
S.date2 <= @date2) AS T2
WHERE (T2.date1, T2.date2, T2.period, T1.market, T1.ticker)
NOT IN
(SELECT S.date1,
S.date2,
S.period,
Q.market,
Q.ticker
FROM portfolio.scenario S , portfolio.quote Q
WHERE Q.date = @qdate AND
Q.market = S.market AND
Q.ticker = S.ticker AND
S.series = @series AND
S.date1 >= @date1 AND
S.date2 <= @date2))
但是,如果我改變
(@series :=
(SELECT S.series
FROM scenario S
WHERE S.date1 >= '2009-09-01' AND
S.date2 <= '2010-07-01' AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1))
是
(@series :=
(SELECT S.series
FROM scenario S
WHERE S.date1 >= @date1 AND
S.date2 <= @date2 AND
S.period = 'QUARTER'
ORDER BY S.date2
LIMIT 1))
需要t處理它很多時間(我已經執行了查詢10分鐘前,仍然沒有得到結果),而查詢通常在5秒內返回。
另外,當我重置變量,執行結果不正確(可能使用前一次執行的變量值)。我怎樣才能改變這種不添加SET語句(我想這是一個單一的查詢)
謝謝你的好建議,但在我的查詢中使用@z:=(SELECT * FROM SubTable WHERE x = @x)這樣的行大大增加了獲取結果集的時間。我已經重新編輯了這個問題,以包含基於您的評論和一些邏輯的新查詢以減少子查詢 – 3ashmawy 2010-11-19 22:22:39
這些節省來自在許多列中使用該變量(我的示例沒有顯示,所以我更新了它) 。我最近將這個應用到了一段總結性的SQL,否則它會爲多列重複窗口平均計算(子選擇+分組函數)。 – 2010-11-19 22:44:30
Thanx兄弟的反饋,是的,我用@series變量的概念。我想你的例子@z:=(SELECT * FROM SubTable WHERE x = @x),SubTable只有一列,因爲@z將無法保存來自多列的值。 – 3ashmawy 2010-11-19 23:18:06