Представьте, что строку с «категорией, категорией 2» можно преобразовать в две строки (одна с «категорией», одна с «категорией 2»), чтобы получить то, что вы хотите. Вы бы сделали это так:
SELECT items.category /* , other columns... */
FROM items
UNION ALL
SELECT items.category2 /* , other columns... */
FROM items
Итак, все, что вам нужно сделать, - это агрегировать по следующим параметрам:
SELECT category, count(*) FROM (
SELECT items.category FROM items
UNION ALL
SELECT items.category2 FROM items
) expanded
GROUP BY category
Вы также можете выполнить агрегирование по следующим этапам, если ваша база данных поддерживает это:
with subcounts as (
select items.category, items.category2, count(*) as subcount
from items
group by category, category2)
select category, sum(subagg) as finalcount from (
select subcounts.category, sum(subcount) as subagg from subcounts group by category
union all
select subcounts.category2, sum(subcount) as subagg from subcounts group by category2
) combination
group by category
Это ограничит только один просмотр таблицы основных предметов, хорошо, если у вас есть только небольшое количество категорий. То же самое можно эмулировать с временными таблицами в базах данных, которые не поддерживают «WITH ...»
EDIT:
Я был уверен, что должен был быть другой способ сделать это, не сканируя Предметы дважды, и есть. Ну, это версия PostgreSQL:
SELECT category, count(*) FROM (
SELECT CASE selector WHEN 1 THEN category WHEN 2 THEN category2 END AS category
FROM Items, generate_series(1,2) selector
) items_fixed GROUP BY category
Единственный бит, специфичный для postgresql, здесь это «generate_series (1,2)», который создает «таблицу», содержащую две строки - одну с «1» и одну с «2». ИМХО, это одна из самых удобных функций в postgresql. Конечно, вы можете реализовывать подобные вещи, например, в SQL Server. Или вы можете сказать «(выберите 1, как объединение селекторов, все выберите 2)». Другой альтернативой является «(values (1), (2)) series (selector)», хотя какая часть этого синтаксиса стандартна, а какая специфична для postgres, я не уверен. Преимущество обоих этих подходов состоит в том, что они дают планировщику представление о том, что будет только два ряда.
Перекрестное объединение элементов таблицы этой серии позволяет нам генерировать две выходные строки для каждой строки элемента. Вы даже можете взять этот подзапрос "items_fixed" и сделать его представлением - кстати, это обратный процесс, который я склонен использовать для решения подобных проблем.