我一直在与一些SQL作斗争,似乎无法理解它。
我有两个表,一个包含类别列表,另一个包含我的所有文章。
我要做的是找出每个类别有多少文章。
这是我到目前为止的SQL
SELECT DISTINCT COUNT( po.post_Cat_ID ) AS Occurances, ca.cat_Title
FROM Posts po, Categories ca
WHERE ca.cat_ID = LEFT( po.post_Cat_ID, 2 )
我使用LEFT的原因是只获取主要类别,因为我列出的类别如下所示...例如
Science = 01
Medicine = 0101
Sport = 02
帖子说asprin因此将cat_ID设为0101.(LEFT然后将0101,0102,0103等修改为01)。基本上我对子类别不感兴趣。
提前致谢
结果
SELECT DISTINCT COUNT( po.post_Cat_ID ) AS Occurances, ca.cat_Title
FROM Posts po, Categories ca
WHERE ca.cat_ID = LEFT( po.post_Cat_ID, 2 )
GROUP BY LEFT( po.post_Cat_ID, 2 )
P.S。感谢@nullpointer,它目前有效,我会考虑重组 为其他读者再次提供链接
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
答案 0 :(得分:0)
我建议您重新构建架构。你想要的是表示一个层次结构(类别),这对于关系数据库来说并不是那么简单。两种常见的解决方案是邻接列表和嵌套集。
邻接列表更像是一种简单的树状结构。您将拥有一个categories
表格,如:
id | name | parent
------------------------
1 | Science | null
2 | Sports | null
3 | Medicine | 1
不幸的是,使用SQL很难处理这个模型。相反,我们可以嵌套集方法。此处每个节点都有lft
和rgt
个值节点,它们位于父级lft
和rgt
值之间。在您的示例中,您将拥有:
id | name | lft | rgt
-------------------------------
1 | Science | 1 | 4
2 | Sports | 5 | 6
3 | Medicine | 2 | 3
因此,为了检索特定类别的计数,您只需查询所需类别之间具有lft
和rgt
值的节点数。例如:
SELECT COUNT(*)
FROM articles a
LEFT JOIN categories c ON a.category_id = c.id
WHERE lft BETWEEN 1 AND 4
AND rgt BETWEEN 1 AND 4
假设您的article
表格如下:
id | ... | category_id
这将在以下详细讨论:
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
我会提出另一个解决方案:使用标签而不是类别。您可以为给定文章使用多个标记,只需获取与特定标记匹配的所有文章的计数。这将更容易使用,也为您提供更多的灵活性。
要实现这一点,您需要在文章和标签之间建立多对多关系,这通常使用联结表来实现:
tags
id | name
articles_tags # the junction table
article_id | tag_id
要标记文章,只需INSERT
articles_tags
个article_id
表中的tag_id
表,其中包含正确的JOIN
和{{1}}。然后你可以像往常一样使用{{1}}来获得你想要的东西。
答案 1 :(得分:0)
向“类别”添加一列,该列提供每个类别所在的主要类别(主要类别为自己)。所以:
cat_id | main_cat_id | title
-------+-------------+---------
01 | 01 | Science
0101 | 01 | Medicine
02 | 02 | Sport
在cat_id = main_cat_id上从中选择以查找主要类别;在left.cat_id = right.main_cat_id上重新连接到自己以查找子类别,然后在cat_id = cat_id上发布帖子。由left.cat_id分组,并通过cat_id和count(*)进行投影。
我在PostgreSQL 8.4中试过这个,我不明白为什么这在MySQL中不起作用,因为查询非常基本。我的桌子:
create table categories(
cat_id varchar(40) primary key,
main_cat_id varchar(40) not null references categories,
title varchar(40) not null
)
create table posts (
post_id integer primary key,
cat_id varchar(40) not null references categories,
title varchar(40) not null
)
我的查询(按标题而不是ID分组):
select m.title, count(*)
from categories m, categories c, posts p
where m.cat_id = c.main_cat_id
and c.cat_id = p.cat_id
group by m.title
更新:我也尝试过使用字符串操作来完成这项工作。查询(在PostgreSQL接受的标准兼容SQL中,而不是MySQL的方言)是:
select m.title, count(*)
from categories m, posts p
where m.cat_id = substring(p.cat_id from 1 for 2)
group by m.title;
哪个工作正常。我无法对速度进行有意义的比较,但对此的查询计划确实看起来比双向连接更简单。