2013-08-22 2 views
3

У меня есть таблица, подобная следующие:Получения суммы значения для двух отдельных диапазонов дат в одном запросе MySQL

|id|empID|date  |tTime| 
| 1| 42|2013-08-04| 8| 
| 2| 42|2013-08-05| 8| 
| 3| 42|2013-08-06| 8| 
| 4| 42|2013-08-11| 8| 
| 5| 42|2013-08-12| 8| 
| 6| 43|2013-08-04| 7| 
| 7| 43|2013-08-05| 7| 
| 8| 43|2013-08-06| 7| 
| 9| 43|2013-08-11| 7| 
|10| 43|2013-08-12| 7| 

Для целей данного вопроса структуры таблицы будет:

CREATE TABLE `table` (
    `id` int(11) unsigned NOT NULL auto_increment, 
    `empID` int(8) default NULL, 
    `date` date default NULL, 
    `tTime` decimal(16,8) default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

Настоящая таблица более вовлекает типы столбцов, а другие детали одинаковы.

мне нужно знать SUM(tTime) для каждого empID для двух разных диапазонов дат (08/04/13 -> 08/10/13 и 08/11/13 -> 08/17/13 в данном случае). Моя цель состоит в том, чтобы в конечном итоге с чем-то вдоль линий:

|empID| A| B| 
| 42| 24| 16| 
| 43| 21| 14| 

В этом случае диапазоны дат являются недели, но это не всегда так, так что диапазоны дат должны быть гибкими.

До сих пор я делаю это с двумя запросами. Я хотел бы иметь возможность сделать это в одном, если это возможно/более эффективно.

SELECT `empID`, SUM(`tTime`) FROM `table` WHERE `date` BETWEEN '2013-08-04' AND '2013-08-10' GROUP BY `empID`; 
SELECT `empID`, SUM(`tTime`) FROM `table` WHERE `date` BETWEEN '2013-08-11' AND '2013-08-17' GROUP BY `empID`; 

Который получает меня:

|empID|SUM(`tTime`)| 
| 42|   24| 
| 43|   21| 

и

|empID|SUM(`tTime`)| 
| 42|   16| 
| 43|   14| 

Это самый эффективный способ для меня, чтобы получить результаты, Я ищу или есть лучший способ делать это?

+0

Можете ли вы также опубликовать структуру таблицы и информацию об использовании механизма хранения? –

+0

да, группа - лучший способ для этого требования. – user1502952

ответ

5

Вот один из способов, чтобы получить результат:

SELECT `empID` 
    , SUM(IF(`date` BETWEEN '2013-08-04' AND '2013-08-10',`tTime`,0)) AS A 
    , SUM(IF(`date` BETWEEN '2013-08-11' AND '2013-08-17',`tTime`,0)) AS B 
    FROM `table` 
WHERE `date` BETWEEN '2013-08-04' AND '2013-08-17' 
GROUP BY `empID`; 

«Трюк» использует выражение с условным испытанием, и возвращение TTIME или 0 в зависимости от результата теста.

Это обычно более эффективно, чем два отдельных оператора, это один проход данных и одна операция GROUP BY.

+0

Приятный «трюк» действительно +1, если вы указали KEY (date, empID), это должно быть действительно быстрее. (конечно, поможет, если бы двигатель был InnoDB, но это MyISAM) –

+1

@ Раймонд Ниланд: индекс 'ON (empID, date)' мог бы сделать его еще быстрее для большого набора (в зависимости от распределения данных), если MySQL использует индекса, чтобы оптимизировать операцию GROUP BY и избежать операции «Использование файловой системы».) «EXPLAIN» отобразит план доступа. – spencer7593

+0

Действительно, это имело бы смысл, тогда можно было бы использовать «рывковую индексацию». –

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