2013-12-18 3 views
0

Привет всем, у меня есть длинный запрос, и я пытаюсь уменьшить его с меньшим количеством слов и попытаться его оптимизировать.Как я могу оптимизировать свой запрос, используя 2 таблицы?

Вот мой запрос:

SET @year := 2013; 
SET @euro := 3.14; 

SELECT 
SUM(IF (CONCAT(@year, '-01') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Jan, 
SUM(IF (CONCAT(@year, '-02') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Feb, 
SUM(IF (CONCAT(@year, '-03') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Mar, 
SUM(IF (CONCAT(@year, '-04') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Apr, 
SUM(IF (CONCAT(@year, '-05') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) May, 
SUM(IF (CONCAT(@year, '-06') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Jun, 
SUM(IF (CONCAT(@year, '-07') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Jul, 
SUM(IF (CONCAT(@year, '-08') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Aug, 
SUM(IF (CONCAT(@year, '-09') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Sep, 
SUM(IF (CONCAT(@year, '-10') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Oct, 
SUM(IF (CONCAT(@year, '-11') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) Nov, 
SUM(IF (CONCAT(@year, '-12') BETWEEN date_format(date_ini, '%Y-%m') AND date_format(date_expired, '%Y-%m'),i.net_insurance * IF (type_money = 2, @euro, 1), 0)) `Dec` 

FROM insurances i 
INNER JOIN policies p ON p.id = i.policy_id 
WHERE (i.initial_date >= p.date_ini 
AND i.final_date <= p.date_expired) 

Вот мой результат:

JAN  FEB MAR  APR MAY  JUN JUL  AUG SEP  OCT NOV  DEC 
20286 20286 26496 26496 26496 26496 26496 26496 9936 9936 9936 9936 

Вот мой демо: http://sqlfiddle.com/#!2/074ff/1

Пожалуйста, кто-нибудь может мне помочь?

Я по-настоящему признателен за помощь.

ответ

2

Вот альтернатива для вас.

Это может быть немного дольше из-за создания @sqlvars, но это должно помочь пару способов.

Первый FROM (подзапрос, создающий sqlvars) ничего не делает, кроме создания 12 простых переменных, представляющих дату «dt» каждого месяца Jan-Dec в качестве формата даты, и мы избавляемся от конкатенации символьной строки, сделанной на каждой записи для даты и соответствующих дат /.

Второй FROM (подзапрос запрашивает только те квалифицированные записи для диапазона дат вопроса, но в то время как там, он вычисляет коэффициент @euro есть в конечное имя столбца «InsAmount».

Наконец, те, слиты вместе упрощает SUM() совокупный коэффициент читаемости.

SET @euro := 3.14; 

SELECT 
     SUM(IF (@dtJan BETWEEN date_ini AND date_expired, InsAmount, 0)) Jan, 
     SUM(IF (@dtFeb BETWEEN date_ini AND date_expired, InsAmount, 0)) Feb, 
     SUM(IF (@dtMar BETWEEN date_ini AND date_expired, InsAmount, 0)) Mar, 
     SUM(IF (@dtApr BETWEEN date_ini AND date_expired, InsAmount, 0)) Apr, 
     SUM(IF (@dtMay BETWEEN date_ini AND date_expired, InsAmount, 0)) May, 
     SUM(IF (@dtJun BETWEEN date_ini AND date_expired, InsAmount, 0)) Jun, 
     SUM(IF (@dtJul BETWEEN date_ini AND date_expired, InsAmount, 0)) Jul, 
     SUM(IF (@dtAug BETWEEN date_ini AND date_expired, InsAmount, 0)) Aug, 
     SUM(IF (@dtSep BETWEEN date_ini AND date_expired, InsAmount, 0)) Sep, 
     SUM(IF (@dtOct BETWEEN date_ini AND date_expired, InsAmount, 0)) Oct, 
     SUM(IF (@dtNov BETWEEN date_ini AND date_expired, InsAmount, 0)) Nov, 
     SUM(IF (@dtDec BETWEEN date_ini AND date_expired, InsAmount, 0)) `Dec` 
    from 
     (select 
       @dtJan := '2013-01-01', 
       @dtFeb := DATE_ADD(@dtJan, INTERVAL 1 MONTH), 
       @dtMar := DATE_ADD(@dtFeb, INTERVAL 1 MONTH), 
       @dtApr := DATE_ADD(@dtMar, INTERVAL 1 MONTH), 
       @dtMay := DATE_ADD(@dtApr, INTERVAL 1 MONTH), 
       @dtJun := DATE_ADD(@dtMay, INTERVAL 1 MONTH), 
       @dtJul := DATE_ADD(@dtJun, INTERVAL 1 MONTH), 
       @dtAug := DATE_ADD(@dtJul, INTERVAL 1 MONTH), 
       @dtSep := DATE_ADD(@dtAug, INTERVAL 1 MONTH), 
       @dtOct := DATE_ADD(@dtSep, INTERVAL 1 MONTH), 
       @dtNov := DATE_ADD(@dtOct, INTERVAL 1 MONTH), 
       @dtDec := DATE_ADD(@dtNov, INTERVAL 1 MONTH)) sqlvars, 
     (select 
       date_ini, 
       date_expired, 
       i.net_insurance * IF (type_money = 2, @euro, 1) as InsAmount 
      from 
       insurances i 
       INNER JOIN policies p ON i.policy_id = p.id 
      WHERE 
        i.initial_date >= p.date_ini 
       AND i.final_date <= p.date_expired) as QryRecs 
+0

благодарит @DRapp, но это оптимизация? потому что я хотел меньше кода =) –

+0

@CarlitosMorales, меньше кода? не обязательно, но я бы подумал о запуске некоторых временных тестов на нем против вашего и увидеть разницу. ИНОГДА, немного больше (например, подготовка 12 переменных в месяц) и предварительная сбор ваших квалифицированных записей за раз в евро или нет, может значительно улучшить читаемость кода ... что в свою очередь может привести к упрощению обслуживания , – DRapp

+0

спасибо, кстати, я узнал что-то еще =) –

1

Вы пытаетесь сделать сводный запрос, который MySQL не поддерживает. Как вы можете видеть, обходной путь становится ОЧЕНЬ уродливым, ОЧЕНЬ быстрым.

Вашего ТОЛЬКО альтернативы, чтобы перейти к СУБД, которая не поддерживает PIVOT запросов, или вернуться к обычному SELECT ... FROM ... запросу БЕЗ всех логик условного столбца и выполните rows-> преобразование столбцов в коде на стороне клиента.

+0

Как должен быть запрос с меньшим количеством слов? –

+0

канавы все те, 'SUM (IF (' биты, и имеют простой 'выбрать field_you_want FROM table'. Затем используйте свой код на стороне клиента для преобразования отдельных значений строк в набор данных с несколькими столбцами. Другими словами, запрос –

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