Я получаю неожиданные результаты, когда я использую SUM (CASE WHEN .... THEN "column_name") в sqlite3 - PullRequest
0 голосов
/ 02 апреля 2020

Я пытаюсь найти количество заказов, которые я получил в апреле месяце. У меня 3 заказа, но мой запрос дает результат 0. В чем может быть проблема?

Вот таблица:

id | first   | middle | last    | product_name  | numberOut | Date
1 | Muhammad | Sameer | Khan    | Macbook       | 1         | 2020-04-01
2 | Chand    | Shah   | Khurram | Dell Optiplex | 1         | 2020-04-02
3 | Sultan   |        | Chohan  | HP EliteBook  | 1         | 2020-03-31
4 | Express  | Eva    | Plant   | Dell Optiplex | 1         | 2020-03-11
5 | Rana     | Faryad | Ali     | HP EliteBook  | 1         | 2020-04-02

А вот запрос:

SELECT SUM(CASE WHEN strftime('%m', oDate) = '04' THEN 'id' END) FROM orders;

Ответы [ 5 ]

3 голосов
/ 02 апреля 2020

Если вы хотите все апреля, то вы можете просто посмотреть на месяц. Я бы порекомендовал:

select count(*)
from orders o
where o.date >= '2020-04-01' and o.date < '2020-05-01';

Обратите внимание, что это делает прямые сравнения date с действительными датами в предложении where.

3 голосов
/ 02 апреля 2020

Проблема с вашим кодом заключается в следующем:

THEN 'id'

Вы используете агрегатную функцию SUM() и суммируете по строковому литералу, например 'id', который неявно преобразуется в 0 (потому что он не может быть преобразован в число), поэтому результат равен 0. Даже если вы удалите одинарные кавычки, вы не получите желаемый результат, потому что вы получите сумму id s. Но если бы вы использовали:

THEN 1 ELSE 0

, то вы получите правильный результат. Но с SQLite вы можете написать это проще:

SELECT SUM(strftime('%m', oDate) = '04') FROM orders;

без выражения CASE. Или, поскольку вы просто хотите посчитать заказы, тогда COUNT() сделает это:

SELECT COUNT(*) FROM orders WHERE strftime('%m', oDate) = '04';

Редактировать. Если вы хотите посчитать заказы за все месяцы, группируйте по месяцам:

SELECT strftime('%Y-%m', oDate) AS month, 
       COUNT(*) AS number_of_orders
FROM orders 
GROUP BY month;
1 голос
/ 02 апреля 2020
SELECT SUM(CASE WHEN strftime('%m', oDate) = '04' THEN 1 ELSE 0 END) FROM orders; 

, если вам нужно использовать SUM

1 голос
/ 02 апреля 2020

Я бы использовал явные сравнения дат, а не функции даты - это делает запрос SARGeable, ie это может принести пользу существующему индексу.

Наиболее эффективный подход с фильтром в предложении where :

select count(*) cnt
from orders 
where oDate >= '2020-04-01' and oDate < '2020-05-01'

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

select sum(case when oDate >= '2020-04-01' and oDate < '2020-05-01' then 1 else 0 end) cnt
from orders
1 голос
/ 02 апреля 2020

Проблема с вашим запросом. Вам не нужно делать эту операцию агрегирования.

SELECT COUNT(*) from table_name WHERE strftime('%m', Date) = '04';
...