Элементы и категории (1: N) Как получить общее количество активных элементов для каждой категории в одном SQL-запросе?

#mysql #sql

#mysql #sql

Вопрос:

Товары

 item_id
title
active = 1/0
  

items_categories_map

 item_id
category_id
  

Мне нужно получить результат

 category_id
items_total (any value of items.active)
items_active (items.active = 1)
items_inactive (items.active = 0)
  

Возможно ли получить такой результат в одном SQL-запросе без использования ОБЪЕДИНЕНИЯ?

Спасибо!

Ответ №1:

Используйте шаблон, подобный следующему…

 COUNT(items.active) AS items_total,
SUM(items.active)   AS items_active,
SUM(1-items.active) AS items_inactive
  

Или когда у вас есть значения, которые не равны 1 или 0…

 SUM(CASE WHEN items.active = 0 THEN 1 ELSE 0 END) as items_inactive
  

Комментарии:

1. Если active никогда не может быть NULL, это также может сделать: COUNT(NULLIF(items.active, 0)) AS items_active, COUNT(NULLIF(items.active, 1)) AS items_inactive .

Ответ №2:

Для добавления в Dems: если вы хотите сгруппировать по и также иметь общее количество, используйте:

 select items.id
 , COUNT(items.active) AS items_total
 , SUM(ifnull(items.active,0)) AS items_active
 , SUM(1-ifnull(items.active,0)) AS items_inactive
FROM items
GROUP BY items.somefield WITH ROLLUP

 ------ ------------- --------------- ---------------- 
| id   | items_total | items_active  | items_inactive |
 ------ ------------- --------------- ---------------- 
| 1    | 2           | 1             | 1              |
| 2    | ....
| null |100          | 60            | 40             |<<- grand total
 ------ ------------- --------------- ---------------- 
  

with rollup вы получите общую строку внизу.

требуется ли количество?
Если items.active может иметь значение null, вам понадобится ifnull() там, чтобы предотвратить вычисление суммы до null и испортить ваш результат.

Комментарии:

1. Ваша логика рассматривает нулевую запись как неактивную. Если это на самом деле ни активный, ни неактивный, вам нужно было бы переместить 1- часть внутри IFNULL… SUM(ifnull(1-items.active,0))

2. @dems, да, да, ярлыки. Вы действительно должны определить поле active как логическое, а не нулевое значение по умолчанию 0 (или 1) Я знаю, я просто указывал, как убедиться, что ваши суммы не возвращают null, вам решать, делать предположения и писать код соответственно.

3. @Andriy M откатил ваши изменения и переделал их, потому что мне было любопытно, что будет делать новая опция отката.

4. Это совершенно нормально. На самом деле я рад, что вы нашли мои изменения полезными и их стоит переделать. Итак, спасибо, что сообщили мне об этом.