简体   繁体   中英

Sql getting count of each category

Consider the following 2 tables

Categories

CatId       CatName         HigerCatId
1           Clothing        0
2           Jackets         1      
3           T-Shirts        1
4           BlueT-Shirts    3
5           White-Jackates  2

if higher HigerCatId is 0 it means we reached the the top parent and we should stop

Products

ProductId   CatId
0           3
1           1
2           1
3           2
4           2
5           3
6           4
7           3
8           4

the expected result is

CatName         ChildCats      ProductsCount   ProductIds(Not needed just to give an idea)
Clothing        2,3,4,5        9               0,1,2,3,4,5,6,7,8
Jackets         5              2               3,4
T-Shirts        4              5               0,5,6,7,8
BlueT-Shirts    none           2               6,8 
White-Jackates  none           0               none

all i need is to get the total count of products that fall under a category, the total for the parent should contain the total of all categories under it. i was able to do it with recursion in c# and i have no idea if its even possible directly from sql, my problem is that sub categories can have products even if they have deeper sub categories, is that result producible in a totally dynamic way from sql server no matter how the depth of the levels is or should i stick to do it from outside sql?

if its possible can you please give me some ideas?

200 bounty will be rewarded when i get to start one.

You need a CTE

WITH cte
     AS
     (
         SELECT CatId    AS ParentCatId,
                CatName,
                CatName  AS ParentName,
                HigherCatId,
                CatId,
                CAST(CatName AS VARCHAR(255)) AS PATH
         FROM   Categories
         UNION ALL 
         SELECT c.CatId    AS ParentCatId,
                cte.CatName,
                c.CatName  AS ParentName,
                c.HigherCatId,
                cte.CatId,
                CAST(cte.path + ', ' + c.CatName AS VARCHAR(255)) AS PATH
         FROM   cte
                INNER JOIN Categories c
                     ON  c.CatId = cte.HigherCatId
     )

SELECT c.parentName,
       COUNT(p.ProductId) AS ProductsCount
FROM   cte c
       LEFT OUTER JOIN products p
            ON  c.CatId = p.CatId
GROUP BY
       c.ParentCatId,
       c.ParentName
ORDER BY
       c.ParentCatId

There are some extra columns for debugging purposes, you can remove them in your final code.

Check out the SQL Fiddle where you can see the result and some intermediate outputs.

CTE can create the hierarchy.

XML path can concatinate the columns.

Count(p.CatId) in combination with GROUP BY will get the exact number of matches(ProductCount)

;WITH cte AS
(
  SELECT 
    CatId parent, 
    CatId 
  FROM Categories
  UNION ALL 
  SELECT 
    cte.parent, 
    c.CatId
  FROM cte
  JOIN
    Categories c 
  ON cte.CatId = c.HigherCatId
)
SELECT c.CatName, 
    Coalesce(STUFF(( 
        SELECT 
          ',' + cast(t1.CatId as varchar(10))
        FROM 
          cte t1 
        WHERE 
          t1.parent = c.CatId and
          t1.CatId <> c.CatId
        ORDER BY 
          t1.CatId
        for xml path(''), type 
    ).value('.', 'varchar(max)'), 1, 1, ''), 'none') ChildCats,
    COUNT(p.CatId) ProductCount,
    COALESCE(STUFF(( 
        SELECT ',' + cast(p.ProductId as varchar(10))
        FROM cte t1 
        LEFT JOIN
          Products p 
        ON
          t1.CatId = p.CatId
        WHERE 
          t1.parent = c.CatId 
        ORDER BY 
          p.ProductId
        for xml path(''), type 
    ).value('.', 'varchar(max)'), 1, 1, ''), 'none') ProductIds
FROM 
  Categories c 
JOIN
  cte 
ON 
  c.CatId = cte.parent
LEFT JOIN
  Products p
ON
  cte.CatId = p.CatId
GROUP BY 
  c.CatId, 
  c.CatName
ORDER BY 
  c.CatId

FIDDLE

Result:

CatName        ChildCat   ProductCount  ProductIds
Clothing       2,3,4,5    9             0,1,2,3,4,5,6,7,8
Jackets        5          2             3,4
T-Shirts       4          5             0,5,6,7,8
BlueT-Shirts   none       2             6,8
White-Jackates none       0             none

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM