2008-11-11 153 views
2

通常,您需要显示数据库项目的列表以及有关每个项目的特定总数。例如,当您在堆栈溢出中键入标题文本时,将出现相关问题列表。该列表显示了相关条目的标题以及每个标题的单个合计答复数量。查询:计算每个项目的多个总计数

我有一个类似的问题,但需要多个聚合。我想在任何的3种格式,具体取决于用户选择显示的项目清单:

  • 我的项目的名称(15总,13由我拥有)
  • 我的项目的名称(15个)
  • (我拥有的13)
  • 我的项目的名称

我的数据库是:

  • 项目:的itemId,ITEMNAME, OWNERID
  • :CATID,catName
  • 地图:的azazaz,的itemId,CATID

下面的查询获取:类别名称,每个类别

SELECT 
    categories.catName, 
    COUNT(map.itemId) AS item_count 
FROM categories 
LEFT JOIN map 
    ON categories.catId = map.catId 
GROUP BY categories.catName 

项ID的数这一个得到:类别名称,每个类别的这个owner_id的物品id的数量只有

SELECT categories.catName, 
COUNT(map.itemId) AS owner_item_count 
FROM categories 
LEFT JOIN map 
    ON categories.catId = map.catId 
LEFT JOIN items 
    ON items.itemId = map.itemId 
WHERE owner = @ownerId 
GROUP BY categories.catId 

但是我如何在单个查询中同时获取它们? I.e .:类别名称,每个类别的物品ID计数,仅针对该owner_id的每个类别的物品ID计数

奖励。我可以选择只检索其中任何一个的catId数!= 0。在试图“WHERE ITEM_COUNT <> 0”,我得到:

MySQL said: Documentation 
#1054 - Unknown column 'rid_count' in 'where clause' 

回答

5

这里有一个窍门:计算被称为是1或0值的SUM()等价于值为1的行的COUNT() 。你知道一个布尔比较返回1或0(或NULL)。

SELECT c.catname, COUNT(m.catid) AS item_count, 
    SUM(i.ownerid = @ownerid) AS owner_item_count 
FROM categories c 
    LEFT JOIN map m USING (catid) 
    LEFT JOIN items i USING (itemid) 
GROUP BY c.catid; 

至于奖金问题,你可以简单地做一个内部联接,而不是外部连接,这意味着仅类别与至少一排map将返回。

SELECT c.catname, COUNT(m.catid) AS item_count, 
    SUM(i.ownerid = @ownerid) AS owner_item_count 
FROM categories c 
    INNER JOIN map m USING (catid) 
    INNER JOIN items i USING (itemid) 
GROUP BY c.catid; 

这里的另一种解决方案,这是效率不高,但我会告诉它来解释为什么你得到了错误:

SELECT c.catname, COUNT(m.catid) AS item_count, 
    SUM(i.ownerid = @ownerid) AS owner_item_count 
FROM categories c 
    LEFT JOIN map m USING (catid) 
    LEFT JOIN items i USING (itemid) 
GROUP BY c.catid 
HAVING item_count > 0; 

不能在WHERE子句中使用列别名,因为在选择列表中的表达式之前评估WHERE子句中的表达式。换句话说,与选择列表表达式相关的值尚不可用。

您可以在GROUP BYHAVINGORDER BY子句中使用列别名。这些子句在选择列表中的所有表达式都被评估后运行。

4

你可以偷偷CASE语句的SUM()内:

SELECT categories.catName, 
    COUNT(map.itemId) AS item_count, 
    SUM(CASE WHEN owner= @ownerid THEN 1 ELSE 0 END) AS owner_item_count 
FROM categories 
LEFT JOIN map ON categories.catId = map.catId 
LEFT JOIN items ON items.itemId = map.itemId 
GROUP BY categories.catId 
HAVING COUNT(map.itemId) > 0 
2
SELECT categories.catName, 
    COUNT(map.itemId) AS item_count, 
    COUNT(items.itemId) AS owner_item_count 
FROM categories 
INNER JOIN map 
    ON categories.catId = map.catId 
LEFT JOIN items 
    ON items.itemId = map.itemId 
    AND items.owner = @ownerId 
GROUP BY categories.catId 

请注意,您可以在owner_item_count使用HAVING条款,但内部加入照顾ITEM_COUNT的为您服务。

相关问题