Расширенный запрос SQL GROUP BY - PullRequest
3 голосов
/ 13 мая 2009

У меня есть два столбца в моей таблице «Категории», «Категория2», эти два столбца содержат, по сути, одну и ту же информацию. Если бы я спроектировал базу данных, я бы создал отдельную таблицу для категорий и добавил бы элементы к категориям на основе этой таблицы, к сожалению, я не создал базу данных и не могу изменить ее сейчас, но я думаю, что все еще есть способ сделать то, что я хочу сделать.

Пример таблицы показан ниже

Category             Category2
------------------   -----------------
truck                full size - pickup
full size - pickup   truck
Sedan                Import - Sedan
Convertible          Domestic - Coupe

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

SELECT Category, Count(*) as Count
FROM Items
GROUP BY Category, Category2

Ответы [ 5 ]

14 голосов
/ 13 мая 2009

Просто скопируйте обе категории в один столбец перед группировкой.

SELECT Category, Count(*) as TheCount
FROM
(
  SELECT Category1 as Category
  FROM Items
  UNION ALL
  SELECT Category2
  FROM Items
) sub
GROUP BY Category
7 голосов
/ 13 мая 2009

Представьте, что строку с «категорией, категорией 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" и сделать его представлением - кстати, это обратный процесс, который я склонен использовать для решения подобных проблем.

2 голосов
/ 13 мая 2009

1001 * попробовать *

select category,sum(CategoryCount)
from(
select Category1 as category, count(Category1) as CategoryCount
from Table
group by Category1
union all
select Category2 as category, count(Category2) as CategoryCount
from Table
group by Category2) x
group by category
1 голос
/ 13 мая 2009

Я уверен, что есть лучший способ сделать это, но здесь вы идете

declare @group1 (Category1, Count int)
declare @group2 (Category2, Count int)

insert into @group1 (Category1, Count1)
select Category1, count(Category1)
from Table
group by Category1

insert into @group2 (Category2, Count2)
select Category2, count(Category2)
from Table
group by Category2

select 
coalesce(Category1, Category2) as Category,
coalesce(Count1,0) + coalesce(Count2,0) as CountAll
from @group1 a
    full outer join @group2 b
        on a.Category1=b.Category2
0 голосов
/ 13 мая 2009

попробуйте

выберите тип как 1, количество (*) как количество из таблицы, где категория как '% полный размер - пикап%'

союз

выберите тип как 2, количество (*) как количество из таблицы, где категория типа "% truck%"

союз

выберите тип 3, количество (*) как количество из таблицы, где категория, например, "% sedan%"
и так далее ......

тип 1 будет вашим полноразмерным счетчиком введите 2 количество грузовиков и так далее ...

надеюсь, это поможет

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