Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / MySQL Новый топик    Ответить
 Применение оператора SUM() для суммирования по нескольким разным промежуткам.  [new]
Hofmann
Member

Откуда:
Сообщений: 2
Есть, например, такая таблица Table:

id Class Qty
1A4
2B6
3C9
4A12
5B8
6C20
7A1
8B5
9C13

Я хочу просуммировать столбец Qty по разным промежуткам id сгруппировав их по столбцу Class.
Исходя из таблицы выше, мне нужно получить следующую таблицу:


ClassSumQty1SumQty2SumQty3
A1610
B685
C92013

где
SumQty1 - сумма по Qty с условие того, что 1 <= id <= 4,
SumQty2 - сумма по Qty с условие того, что 5 <= id <= 7,
SumQty3 - сумма по Qty с условие того, что 8 <= id <= 9.
Хочу обратить внимание, что промежутки разной длины.


Я сделал это с использованием подзапросов следующий образом:

SELECT
     ClassX AS Class 
     Qty1, 
     Qty2, 
     Qty3
FROM 
     (SELECT
          Class AS ClassX
          SUM(Qty) AS SumQty1
      FROM
          Table
      WHERE id BETWEEN 1 AND 4
      GROUP BY Class) AS X
JOIN
     (SELECT
          Class AS ClassY
          SUM(Qty) AS SumQty2
      FROM
          Table
      WHERE id BETWEEN 5 AND 7
      GROUP BY Class) AS Y
ON X.ClassX = Y.ClassY
JOIN
     (SELECT
          Class AS ClassZ
          SUM(Qty) AS SumQty3
      FROM
          Table
      WHERE id BETWEEN 8 AND 9
      GROUP BY Class) AS Z
ON Y.ClassY = Z.ClassZ
ORDER BY Class

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

Есть ли какой-то способ сформировать запрос так, чтобы мы всего один раз прошли по значениям таблицы, проверили три промежутка и вывели суммы по этим промежуткам?

То есть, в общем, меня интересует можно ли как-то уменьшить скорость выполнения такого запроса.
8 мар 18, 22:53    [21245444]     Ответить | Цитировать Сообщить модератору
 Re: Применение оператора SUM() для суммирования по нескольким разным промежуткам.  [new]
vkle
Member

Откуда: Самара
Сообщений: 13900
Навскидку так примерно
SELECT
    COUNT(`id` BETWEEN 1 AND 4) AS `SumQty1`,
    COUNT(`id` BETWEEN 5 AND 7) AS `SumQty2`,
    COUNT(`id` BETWEEN 8 AND 9) AS `SumQty3`
FROM `Table`
GROUP BY `Class`
8 мар 18, 23:05    [21245459]     Ответить | Цитировать Сообщить модератору
 Re: Применение оператора SUM() для суммирования по нескольким разным промежуткам.  [new]
vkle
Member

Откуда: Самара
Сообщений: 13900
Прошу пардону, NULLIF забыл воткнуть. Так:

    COUNT(NULLIF(`id` BETWEEN 1 AND 4, 0)) AS `SumQty1`,
8 мар 18, 23:14    [21245466]     Ответить | Цитировать Сообщить модератору
 Re: Применение оператора SUM() для суммирования по нескольким разным промежуткам.  [new]
vkle
Member

Откуда: Самара
Сообщений: 13900
Глупость выше написал, Вам же сумма нужна, а не количество.
8 мар 18, 23:21    [21245472]     Ответить | Цитировать Сообщить модератору
 Re: Применение оператора SUM() для суммирования по нескольким разным промежуткам.  [new]
vkle
Member

Откуда: Самара
Сообщений: 13900
Ну, смысл тот же
SELECT
    SUM(IF(`id` BETWEEN 1 AND 4, `Qty`, 0)) AS `SumQty1`,
    SUM(IF(`id` BETWEEN 5 AND 7, `Qty`, 0)) AS `SumQty2`,
    SUM(IF(`id` BETWEEN 8 AND 9, `Qty`, 0)) AS `SumQty3`
FROM `Table`
GROUP BY `Class`
8 мар 18, 23:36    [21245484]     Ответить | Цитировать Сообщить модератору
 Re: Применение оператора SUM() для суммирования по нескольким разным промежуткам.  [new]
Hofmann
Member

Откуда:
Сообщений: 2
vkle,

Спасибо большое за Ваш вариант. Я пробовал написать что-то похожее, только с оператором CASE и это выглядело так:

SELECT
    SUM(CASE WHEN `id` BETWEEN 1 AND 4 THEN `Qty` ELSE 0 END) AS `SumQty1`,
    SUM(CASE WHEN `id` BETWEEN 5 AND 7 THEN `Qty` ELSE 0 END) AS `SumQty2`,
    SUM(CASE WHEN `id` BETWEEN 8 AND 9 THEN `Qty` ELSE 0 END) AS `SumQty3`
FROM `Table`
GROUP BY `Class`


Что в принципе аналогично IF, как мне кажется. Но у меня всё равно возникает вопрос. Разве каждый оператор SUM() не проходится отдельно по таблице? То есть для первого оператора SUM() ищутся совпадения по всей таблице по условию IF или CASE, потом тоже самое по второму и третьему операторам.
9 мар 18, 00:50    [21245541]     Ответить | Цитировать Сообщить модератору
 Re: Применение оператора SUM() для суммирования по нескольким разным промежуткам.  [new]
vkle
Member

Откуда: Самара
Сообщений: 13900
Hofmann
Что в принципе аналогично IF, как мне кажется.
Кажется, в общем, правильно. С алгоритмической точки зрения оператор ветвления if...else является базовым, его можно использовать при написании более сложных конструкций, таких как case. В данном случае в case проверяется лишь одно условие, а значит, и при развертывании алгоритма там будет использован лишь один if...else. В некотором смысле case тут избыточен. :)

Hofmann
Разве каждый оператор SUM() не проходится отдельно по таблице?
Из таблицы извлекается и обрабатывается строка, где поля id и Qty присутствуют и, следовательно, их значения могут быть использованы где угодно. В данном случае значения используются в трех выражениях.
9 мар 18, 05:26    [21245600]     Ответить | Цитировать Сообщить модератору
Все форумы / MySQL Ответить