1

我一直在与一些 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 )

ps感谢@nullpointer,它目前有效,我会为其他读者考虑重组,再次链接

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

4

2 回答 2

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

更新:正如 OP 所尝试的那样,我还尝试使用字符串操作来完成这项工作。查询(在 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;

哪个工作正常。我无法就速度提供有意义的比较,但是这个查询计划看起来确实比双向连接的查询计划简单一些。

于 2010-09-04T14:11:32.543 回答
0

让我建议您改为重组架构。您在这里想要的是表示一个层次结构(类别),这对于关系数据库来说并不是很简单。两种常见的解决方案是邻接表和嵌套集。

邻接表更像是一个简单的树状结构。你将有一个categories像这样的表:

id  | name      | parent
------------------------
1   | Science   | null
2   | Sports    | null
3   | Medicine  | 1

不幸的是,这个模型很难使用 SQL 来处理。相反,我们可以使用嵌套集方法。这里每个节点都有lftrgt值节点,它将在父节点lft和值之间rgt。在您的示例中,您将拥有:

id  | name      | lft  | rgt  
-------------------------------
1   | Science   | 1    | 4    
2   | Sports    | 5    | 6 
3   | Medicine  | 2    | 3

因此,为了检索某个类别的计数,您可以简单地查询在您想要的类别之间具有 alft和值的节点的计数。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多个条目。然后你可以像往常一样使用 s 来得到你想要的。articles_tagsarticle_idtag_idJOIN

于 2010-09-04T13:49:32.773 回答