Как посчитать строки детализации во вложенных категориях? - PullRequest
1 голос
/ 23 февраля 2011

Давайте рассмотрим, что у нас есть Категории (с PK в качестве CategoryId) и Продукты (с PK в качестве ProductId). Также предположим, что каждая Category может относиться к своей родительской категории (используя столбец ParentCategoryId в Categories).

Как я могу получить количество товаров по категориям? Родительская категория должна также включать в себя количество всех продуктов всех ее подкатегорий.

Любой более простой способ сделать?

Ответы [ 2 ]

2 голосов
/ 23 февраля 2011

звучит так, как будто вы запрашиваете, было бы неплохо использовать с накоплением

select cola, colb, SUM(colc) AS sumc
from table
group by cola, colb
with rollup

Это даст сумму для колба и сумму накопления для колы. Пример результата ниже. Надеюсь, форматирование работает. Нулевые значения - это сводные суммы для группы.

cola    colb    sumc
1       a       1
1       b       4
1       NULL    5
2       c       2
2       d       3
2       NULL    5
NULL    NULL    10

Пойди и дай мне знать, сработало ли это.

- EDIT

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

Я сделал предположение, что в продуктах есть числовое поле.

with x
as (
    select c.CategoryID, c.parentid, p.number, cast(c.CategoryID as varchar(8000)) as grp, c.CategoryID as thisid
    from Categories as c
    join Products as p on p.Categoryid = c.CategoryID
union all
    select c.CategoryID, c.parentid, p.number, cast(c.CategoryID as varchar(8000))+'.'+x.grp , x.thisid
    from Categories as c
    join Products as p on p.Categoryid = c.CategoryID
    join x on x.parentid = c.CategoryID
)
select x.CategoryID, SUM(x.number) as Amount
from x 
left join Categories a on (a.CategoryID = LEFT(x.grp, case when charindex('.',x.grp)-1 > 0 then charindex('.',x.grp)-1 else 0 end))
                    or (a.CategoryID = x.thisid)
where a.parentid = 0
group by x.CategoryID
1 голос
/ 23 февраля 2011

Предполагая, что продукты могут указывать только на категорию sub , вот вероятное решение проблемы:

SELECT
  cp.CategoryId,
  ProductCount = COUNT(*)
FROM Products p
  INNER JOIN Categories cc ON p.CategoryId = cc.CategoryId
  INNER JOIN Categories cp ON cc.ParentCategoryId = cp.CategoryId
GROUP BY cp.CategoryId

Но если приведенное выше предположение неверно и продукт может ссылаться как на родительскую категорию, так и на подкатегорию, то вот как можно рассчитать продукты в этом случае:

SELECT
  CategoryId = ISNULL(c2.CategoryId, c1.CategoryId),
  ProductCount = COUNT(*)
FROM Products p
  INNER JOIN Categories c1 ON p.CategoryId = c1.CategoryId
  LEFT JOIN  Categories c2 ON c1.ParentCategoryId = c2.CategoryId
GROUP BY ISNULL(c2.CategoryId, c1.CategoryId)

EDIT

Это должно работать для 3 уровней иерархии категорий (категория, подкатегория, подкатегория).

SELECT
  CategoryId = COALESCE(c3.CategoryId, c2.CategoryId, c1.CategoryId),
  ProductCount = COUNT(*)
FROM Products p
  INNER JOIN Categories c1 ON p.CategoryId = c1.CategoryId
  LEFT JOIN  Categories c2 ON c1.ParentCategoryId = c2.CategoryId
  LEFT JOIN  Categories c3 ON c2.ParentCategoryId = c3.CategoryId
GROUP BY ISNULL(c3.CategoryId, c2.CategoryId, c1.CategoryId)

COALESCE выбирает первый ненулевой компонент. Если категория является дочерней, она выбирает c3.Category, который является ее прародителем, если родитель, тогда выбирается ее родитель c2.Category, в противном случае это прародитель (c1.CategoryId).

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

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