2017-01-13 2 views
2

Я написал ниже запрос, который работает, но он невероятно неэффективен и медленный. Что я могу сделать, чтобы сделать его более эффективным? Я понимаю, что это в основном «зацикливание» над каждым идентификатором в системе, их около 500, и для каждого из них выполняется 13 выборочных операторов - я просто не знаю лучшего способа получить эту информацию.MySQL возвращает месяц за месяцем для каждого отдельного идентификатора

Мое поле даты - DATE Поле хранится как YYYY-MM-DD.

SELECT 
id as name, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-01-01' AND '2017-01-31') and id = name) as January, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-02-01' AND '2017-02-31') and id = name) as February, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-03-01' AND '2017-03-31') and id = name) as March, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-04-01' AND '2017-04-31') and id = name) as April, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-05-01' AND '2017-05-31') and id = name) as May, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-06-01' AND '2017-06-31') and id = name) as June, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-07-01' AND '2017-07-31') and id = name) as July, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-08-01' AND '2017-08-31') and id = name) as August, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-09-01' AND '2017-09-31') and id = name) as September, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-10-01' AND '2017-10-31') and id = name) as October, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-11-01' AND '2017-11-31') and id = name) as November, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-12-01' AND '2017-12-31') and id = name) as December, 
(SELECT sum(captured_profit) from me where (date BETWEEN '2017-11-01' AND '2017-12-31') and id = name) as Total, 
from me 
where id is not null 
group by id; 

ответ

1

агрегатные функции, такие как SUM() игнорировать NULLs. Поэтому используйте выражение, чтобы сделать значение прибыли NULL, если оно не попадает в диапазон, который вы хотите.

SELECT 
    id AS name, 
    SUM(CASE WHEN MONTH(date) = 1 THEN captured_profit END) AS January, 
    SUM(CASE WHEN MONTH(date) = 2 THEN captured_profit END) AS February, 
    SUM(CASE WHEN MONTH(date) = 3 THEN captured_profit END) AS March, 
    SUM(CASE WHEN MONTH(date) = 4 THEN captured_profit END) AS April, 
    SUM(CASE WHEN MONTH(date) = 5 THEN captured_profit END) AS May, 
    SUM(CASE WHEN MONTH(date) = 6 THEN captured_profit END) AS June, 
    SUM(CASE WHEN MONTH(date) = 7 THEN captured_profit END) AS July, 
    SUM(CASE WHEN MONTH(date) = 8 THEN captured_profit END) AS August, 
    SUM(CASE WHEN MONTH(date) = 9 THEN captured_profit END) AS September, 
    SUM(CASE WHEN MONTH(date) = 10 THEN captured_profit END) AS October, 
    SUM(CASE WHEN MONTH(date) = 11 THEN captured_profit END) AS November, 
    SUM(CASE WHEN MONTH(date) = 12 THEN captured_profit END) AS December, 
    SUM(captured_profit) AS Total 
FROM me 
WHERE id IS NOT NULL AND YEAR(date) = 2017 
GROUP BY id; 

Выражение CASE возвращает NULL, если нет матча и не ELSE положения. Прочтите https://dev.mysql.com/doc/refman/5.7/en/case.html для более подробной информации.

Этот запрос устраняет все коррелированные подзапросы. Запрос будет сканироваться через таблицу только один раз.


Я не знаю, в чем смысл вашей «Total» в запросе, но это, кажется, только ноябрь + декабрь. Я не уверен, что это то, что вы намеревались.

Редактировать: Я исправил выражение для Total.

+0

это означает, что я печатал быстро и сделал '11' вместо' 01'. Спасибо :) Позвольте мне попробовать это и сообщить вам, спасибо вам большое! Edit: Booya, это ТОЧНО, что мне нужно. Я буду читать заявления CASE! –

+0

Хорошо, тогда Total может быть просто 'SUM (capture_profit)' в моем примере, так как я использовал условие WHERE для ограничения диапазона до 2017. –

1

Просто группа по годам, месяцам и ид

select id, sum(captured_profit), month(`date`) 
from me 
where id is not null and `date` > '2016-12-31' 
group by year(`date`), month(`date`), id; 

Я думаю, вы не использовали все ключевые слова (название, дата), как ваши фактические имена столбцов, если вы сделали убедитесь в том, их в backticks в каждом запросе.

+0

Хм ... это просто дает мне назад одна сумма - это не разбив его с каждым месяцем. Я использовал «date» в качестве имени для столбца даты, поэтому я поместил его в backticks. Любые другие идеи? –

+0

Просто укажите месяц (дата) в выборе. Если вы хотите имя месяца, вы можете использовать функцию monthname(). @BrianPowell – baao

+0

да, я тоже пробовал ... не повезло. Должно ли мое поле 'date' быть чем-то другим, кроме MySQL' DATE'? Как 'DATETIME' или что-то еще? –

0

Я думаю, что это именно то, что вы ищете

http://www.w3resource.com/mysql/date-and-time-functions/mysql-monthname-function.php

MySQL MONTHNAME() возвращает полное имя месяца для указанной даты. Возвращаемое значение находится в диапазоне от 1 до 12 (с января по декабрь). Она возвращает NULL, когда месяц часть для даты является 0 или более 12

Синтаксис:

MONTHNAME(date1) 
+0

Я как бы искал способ переписать этот запрос, поэтому я не делаю 13 подзадачей для каждого уникального идентификатора ....Но это будет полезно при преобразовании материала, когда я все сделаю. Благодаря! –

+0

@brianPowell может быть, вы можете сделать, как этот SELECT SUM (captured_profit), MONTHNAME (дата), как имя от меня тентовых от NAME он возвращает Serveral строки каждая строка имеет сумму каждый месяц Имя – Sulyman

1

Билл Karwin бил меня к нему, но я также добавил, сумма строк, сгруппированных по годам:

SELECT 
    id as name, 
    SUM(CASE WHEN MONTH(date) = 1 THEN captured_profit ELSE 0 END) AS January, 
    SUM(CASE WHEN MONTH(date) = 2 THEN captured_profit ELSE 0 END) AS February, 
    SUM(CASE WHEN MONTH(date) = 3 THEN captured_profit ELSE 0 END) AS March, 
    SUM(CASE WHEN MONTH(date) = 4 THEN captured_profit ELSE 0 END) AS April, 
    SUM(CASE WHEN MONTH(date) = 5 THEN captured_profit ELSE 0 END) AS May, 
    SUM(CASE WHEN MONTH(date) = 6 THEN captured_profit ELSE 0 END) AS June, 
    SUM(CASE WHEN MONTH(date) = 7 THEN captured_profit ELSE 0 END) AS July, 
    SUM(CASE WHEN MONTH(date) = 8 THEN captured_profit ELSE 0 END) AS August, 
    SUM(CASE WHEN MONTH(date) = 9 THEN captured_profit ELSE 0 END) AS September, 
    SUM(CASE WHEN MONTH(date) = 10 THEN captured_profit ELSE 0 END) AS October, 
    SUM(CASE WHEN MONTH(date) = 11 THEN captured_profit ELSE 0 END) AS November, 
    SUM(CASE WHEN MONTH(date) = 12 THEN captured_profit ELSE 0 END) AS December, 
    SUM(captured_profit) AS Total, 
    YEAR(date) 
from me 
where id is not null 
group by id, YEAR(date) 
union 
SELECT 
    NULL, 
    SUM(CASE WHEN MONTH(date) = 1 THEN captured_profit ELSE 0 END) AS January, 
    SUM(CASE WHEN MONTH(date) = 2 THEN captured_profit ELSE 0 END) AS February, 
    SUM(CASE WHEN MONTH(date) = 3 THEN captured_profit ELSE 0 END) AS March, 
    SUM(CASE WHEN MONTH(date) = 4 THEN captured_profit ELSE 0 END) AS April, 
    SUM(CASE WHEN MONTH(date) = 5 THEN captured_profit ELSE 0 END) AS May, 
    SUM(CASE WHEN MONTH(date) = 6 THEN captured_profit ELSE 0 END) AS June, 
    SUM(CASE WHEN MONTH(date) = 7 THEN captured_profit ELSE 0 END) AS July, 
    SUM(CASE WHEN MONTH(date) = 8 THEN captured_profit ELSE 0 END) AS August, 
    SUM(CASE WHEN MONTH(date) = 9 THEN captured_profit ELSE 0 END) AS September, 
    SUM(CASE WHEN MONTH(date) = 10 THEN captured_profit ELSE 0 END) AS October, 
    SUM(CASE WHEN MONTH(date) = 11 THEN captured_profit ELSE 0 END) AS November, 
    SUM(CASE WHEN MONTH(date) = 12 THEN captured_profit ELSE 0 END) AS December, 
    SUM(captured_profit) AS Total, 
    YEAR(date) 
from me 
where id is not null 
group by YEAR(date)

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