2010-11-19 2 views
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 «s комментарий и какая-то логика, чтобы уменьшить подзапрос мой запрос сейчас:

(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 oo много времени для его обработки (я выполнил запрос 10 минут назад и до сих пор не получил результат), в то время как запрос обычно возвращается через 5 секунд.

Также, когда я возвращаю переменные, выполнение результата неверно (возможно, используйте значение переменной из предыдущего выполнения). Как я могу изменить, что без добавления заявления SET (я хотел бы, чтобы это было один запрос)

ответ

3

Использование MySQL переменные:

SELECT 
    @x := ColumnName, 
    @y := ColumnName2 + @z, 
    @z := (SELECT * FROM SubTable WHERE x = @x), 
    (SELECT * FROM Table2 WHERE X = @z), 
    (SELECT * FROM Table3 WHERE X = @z) 
FROM Table 
WHERE 
    v = @v 
  • Вы можете назначить подвыбор и столбцов значений переменных SQL
  • Вы можете ссылаться на эти переменные в любом месте в заявлении
  • Переменные содержат их значение из предыдущих строк (если установлено)
  • Вы можете повторно использовать подзапросы и другие значения таким образом
+0

Благодарим вас за большой совет. Но в моем запросе, используя такую ​​строку, как @z: = (SELECT * FROM SubTable WHERE x = @x), значительно увеличивают время получения набора результатов. Я повторно отредактировал вопрос, чтобы включить новый запрос на основе вашего комментария и некоторую логику, чтобы уменьшить подзапрос. – 3ashmawy

+1

Экономия там происходит от использования этой переменной в нескольких столбцах (в моем примере не было показано, что поэтому я ее обновил) , Я применил это недавно к фрагменту сводного SQL, который в противном случае имел бы повторяющиеся средние вычисления окон (subselect + grouping functions) для нескольких столбцов. –

+0

Thanx чувак для обратной связи, да я использовал концепцию с переменной @series. И я думаю, что в вашем примере @z: = (SELECT * FROM SubTable WHERE x = @x), SubTable имеет только один столбец, так как @z не сможет хранить значения из нескольких столбцов. – 3ashmawy

 Смежные вопросы

  • Нет связанных вопросов^_^