Укажите столбец SUM при использовании CASE - PullRequest
0 голосов
/ 30 ноября 2011

Я в основном пытаюсь суммировать значения определенного столбца.Теперь мой запрос выглядит так:

SELECT
DATE(paid_at) AS day,
(SELECT sum(shipping_costs) from orders where shipping_method = 'mondial_relais' and DATE(paid_at) = day) as mr_revenue_real
FROM orders
WHERE MONTH(paid_at) = 10
AND YEAR(paid_at) = 2011
GROUP BY day;

Я хочу заменить подзапрос на mr_revenue_real, чтобы повысить производительность, но я не уверен, как это сделать.Это то, что я имел в виду: sum(case when hipping_method = 'mondial_relais' and DATE(paid_at) = day then 1 end) as mr_revenue_real, но это не сработает, потому что я нигде не указываю, что мне нужна сумма стоимости доставки.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 30 ноября 2011
sum(case when  shipping_method='mondial_relais' then shipping_costs else 0 end)

полный запрос:

SELECT
 DATE(paid_at) AS day,
 sum(case when  shipping_method='mondial_relais' then shipping_costs else 0 end)
FROM orders
WHERE MONTH(paid_at) = 10 AND YEAR(paid_at) = 2011
GROUP BY day;
1 голос
/ 30 ноября 2011

Вроде так:

    SELECT
       DATE(paid_at) AS day,
       sum(case when shipping_method = 'mondial_relais' 
           then shipping_costs end) as mr_revenue_real
    FROM orders
    WHERE MONTH(paid_at) = 10
    AND YEAR(paid_at) = 2011
    GROUP BY day;

(вам не нужно указывать DATE(paid_at) = day, потому что вы уже группируете по DATE(paid_at) AS day.)

0 голосов
/ 30 ноября 2011

Сначала замените:

WHERE MONTH(paid_at) = 10 AND YEAR(paid_at) = 2011

с:

WHERE paid_at >= '2011-10-01'
  AND paid_at <  '2011-10-01' + INTERVAL 1 MONTH

так что, если у вас есть индекс на paid_at, он будет использоваться, и запросу не придется сканировать всю таблицу и вызывать функции YEAR() и MONTH() для каждой строки.


Во-вторых, вам не нужен подзапрос в списке SELECT. Вы можете использовать что-то вроде этого:

SELECT
    DATE(paid_at) AS day,
    SUM( CASE WHEN shipping_method = 'mondial_relais'
                  THEN shipping_costs
              ELSE 0
         END
       ) AS mr_revenue_real
FROM orders
WHERE paid_at >= '2011-10-01'
  AND paid_at <  '2011-10-01' + INTERVAL 1 MONTH
GROUP BY DATE(paid_at)

Вы также можете использовать этот запрос, который, вероятно, будет быстрее с индексом (shipping_method, paid_at). Это, однако, не покажет ни одного дня без заказа с shipping_method = 'mondial_relais':

SELECT
    DATE(paid_at) AS day,
    SUM(shipping_costs) AS mr_revenue_real
FROM orders
WHERE shipping_method = 'mondial_relais'
  AND paid_at >= '2011-10-01'
  AND paid_at <  '2011-10-01' + INTERVAL 1 MONTH
GROUP BY DATE(paid_at)
...