2015-09-25 2 views
1

У меня есть две таблицы: table_car и table_order:

enter image description here enter image description hereУлучшение MySQL скорость запроса с условием длиной даты диапазона

Я хочу таблицу, как это: enter image description here

table_order имеет составной ключ (id_type, date)

SELECT "September" AS `Range`, 
SUM(IF(id_type IN(1,2), items,0)) AS 'RedandBlue_items', 
SUM(IF(id_type IN(3,4), items,0)) AS 'YellowandGreen_items', 
SUM(IF(id_type IN(1,2), items,0)) AS 'RedandBlue_amount', 
SUM(IF(id_type IN(3,4), items,0)) AS 'YellowandGreen_amount' 
FROM table_order 
WHERE id_type IN(1,2,3,4) AND `date` >= "2015-09-01" AND `date` <= "2015-09-30" 
UNION 
SELECT 
"August" AS `Range`, 
SUM(IF(id_type IN(1,2), items,0)) AS 'RedandBlue_items', 
SUM(IF(id_type IN(3,4), items,0)) AS 'YellowandGreen_items', 
SUM(IF(id_type IN(1,2), items,0)) AS 'RedandBlue_amount', 
SUM(IF(id_type IN(3,4), items,0)) AS 'YellowandGreen_amount' 
FROM table_order 
WHERE id_type IN(1,2,3,4) AND `date` >= "2015-08-01" AND `date` <= "2015-08-31" 

Есть ли другие способы быстрого запроса э? Скажем, у меня есть таблица с миллиардами записей и может выполнять запрос длинного диапазона дат в состоянии, например date> = "2015-01-01" и дата < = "2016-01-01".
Вы можете найти образец здесь: http://sqlfiddle.com/#!9/1787e/1

+0

уверен, де-нормировать. – Drew

+0

Не могли бы вы объяснить больше? – sontd

+0

Что такое тип данных 'date' – Drew

ответ

0

1) ваш пример показывает, sum(items) на сумму, которую я предполагаю ошибка копирования.

2) Возможно GROUP_CONCAT является то, что вы ищете

MySQL Doku

Examples

0

Вы также можете попробовать с индексами. Очень полезно во многих случаях: Mysql Indexes

+0

Я использовал индексы для этой таблицы: (id_type, date) – sontd

+0

Так что вы не можете получить больше от этого. Отлично: D Я надеюсь, что вы получите больше идей по оптимизации;) – Luzgan

1

Использование GROUP BY:

SELECT date_format(`date`, '%M') AS `Range`, 
SUM(IF(id_type IN(1,2), items,0)) AS 'RedandBlue_items', 
SUM(IF(id_type IN(3,4), items,0)) AS 'YellowandGreen_items', 
SUM(IF(id_type IN(1,2), items,0)) AS 'RedandBlue_amount', 
SUM(IF(id_type IN(3,4), items,0)) AS 'YellowandGreen_amount' 
FROM `order` 
WHERE id_type IN(1,2,3,4) AND `date` >= "2015-08-01" AND `date` <= "2015-09-30" 
group by year(`date`), month(`date`) 
order by year(`date`) desc, month(`date`) desc; 

http://sqlfiddle.com/#!9/d76254/2

Или держать ваш запрос с профсоюзом, если вы всегда будете всего за два месяца. Но если диапазон может быть намного больше, я предлагаю использовать модифицированный, его гораздо проще написать, и группировка не должна быть узким местом производительности, если вы выберете только относительно небольшую часть таблицы.

Вариант GROUP BY можно сделать быстрее, если вы храните год-месяц в отдельной колонке, поэтому никаких функций не требуется и соответствующим образом изменяйте индексы. Ваш вариант может хорошо использовать индексы без изменений.

Ваш пример (на скрипке) не показывает использование индекса, потому что в таблице слишком мало строк, и в любом случае запрос должен будет прочитать все. Но вы можете добавить covering index(id_type, date, items) (только расширение, которое у вас уже достаточно, не нужно содержать более короткий), что помогает обеим версиям запроса.

Просто проверить объясняет:

+0

отлично! он будет полезен с данными месяца или года. вот что мне нужно, но еще одна проблема: иногда я хочу использовать следующее условие: 'date'> =" 2015-08-15 "AND' date' <= "2015-09-15". Таким образом, с вашим запросом мы не можем группироваться, не так ли? – sontd

+0

@sontd, если вы хотите, чтобы только одна группа из этого диапазона, а не две, тогда вы правы, эта простая группа не сделает этого. Вы можете создать выражение, которое будет работать или использовать ваше оригинальное решение. – jkavalik

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