Mysql 计算表中的实例

Mysql 计算表中的实例,mysql,sql,Mysql,Sql,我有一个标记系统,用于标记博客条目等等。标记位于一个表中,仅包含标记名和主键。然后我有另一个表,其中包含使用标记的对象 它可能看起来像这样: _________________________________ | tags | --------------------------------| | id | name | |-------------------------------| | 1 | S

我有一个标记系统,用于标记博客条目等等。标记位于一个表中,仅包含标记名和主键。然后我有另一个表,其中包含使用标记的对象

它可能看起来像这样:

_________________________________
| tags                          |
--------------------------------|
| id  | name                    |
|-------------------------------|
|  1  | Scuba diving            |
|  2  | Dancing                 |
---------------------------------

_________________________________
| tag_objects                   |
--------------------------------|
| id  | tag  | object           |
|-------------------------------|
|  1  |  2   | 13               |
|  2  |  2   | 18               |
|  3  |  1   | 24               |
---------------------------------
现在,我需要完成的是向tags表添加一列,称为引用或其他内容。对于标记中的每个标记,引用次数应设置为标记在标记对象中使用的次数

基本上类似于伪代码:

foreach(tags):
    UPDATE tags
       SET occurrences = (SELECT COUNT(id) 
                            FROM tag_objects 
                           WHERE tag = tags.id);

当人们将来创建新的帖子和内容时,我只需要一个触发器来更新计数,但是我已经有几千行需要首先计数了。我不知道该怎么做,所以希望您能提供帮助。

我认为,如果您增加或减少表标记对象插入/删除触发器上出现的值,您将获得更好的性能。

您的psuedeo代码在没有foreach循环的情况下将完全按照编写的方式工作。至少在oracle中是这样,我假设MySQL也允许您使用相关子查询作为值。

您已经做了很好的工作,您的查询必须工作

但是,这将导致糟糕的性能。我建议您重新创建一个表:

CREATE TABLE newTags AS
SELECT t.id, t.name, COUNT(*) AS occurrences
FROM tags t
    INNER JOIN tag_objects to
        ON to.tag = tags.id
GROUP BY t.id, t.name

这将非常快。

要插入新行,可以使用如下查询: 在重复键更新出现次数=出现次数+1时,将值X、y、z、1插入标记中;
我没有检查语法,而是类似的东西。

除非你真的需要去规范化你的数据,否则你应该远离它。对索引列的计数通常非常快。我非常喜欢干净规范的数据-

我通常不想在数据库中的列中存储计算出的值-这很混乱,很容易失去同步,并且会冒犯规范化的神

但是,如果您真的必须有一个带有计数的数据库实体,而不是动态计算,我会创建一个视图http://dev.mysql.com/doc/refman/5.0/en/create-view.html 它使用Scorpio提供的SQL存储预先计算的值

CREATE view tag_occurences AS
SELECT t.id, t.name, 
COUNT(*) AS occurrences
FROM tags t
    INNER JOIN tag_objects to
        ON to.tag = tags.id
GROUP BY t.id, t.name

在没有任何额外表格的情况下,最简单的方法是:

首先添加额外字段:

mysql>alter table tags add int 默认为0

然后用出现的次数更新这个新字段

mysql>更新标记左连接选择标记, 作为标记对象的cnt的countid 按标签分组为子Q on tags.id=subq.tag集 发生=聚结子q.cnt,0


请注意,使用left join可以确保统计所有标记,即使是未使用的标记。coalesce函数肯定会将NULL转换为0。

我以后会这样做。然而,我在一个已经有几千行的相当旧的数据库上实现了这一点。我只打算运行一次,然后添加一个触发器来更新它。这不一定是真的。这完全取决于更新/插入/删除的数量!如果这个数字很大,触发器实际上可能会将tags表锁定很长时间,从而大大降低速度!在标准情况下,标签数据的读取多于更改。如果不是的话,标签的使用是有问题的。它也伤害了我的灵魂,但是这个数据库已经屈服了,它经历了比这更糟糕的事情。我们也有相当多的流量,因此需要任何方法来减少数据库在每个页面负载上所做的工作。啊!我明白了在以前的工作中,我处于这种情况。我们花了几个月的时间进行优化,结果达到了50%。通过改变硬件和升级Oracle数据库,我们真正解决了这个问题。德国劳埃德船级社!MySQL不支持物化视图,因此不会存储任何内容。它每次都会运行查询,不需要具体化——它只是将查询填充到视图中,而不是每次都运行它。但是,像你一样,我只是运行查询,而不是浏览视图……你误解了。在MySQL中,通过视图进行查询与直接运行查询完全相同。它不预计算任何值。在优化、执行或表I/O方面,使用视图不会节省任何东西。是的,我知道这一点——但我不认为性能是问题中最重要的。事实上,他根本没有提到性能问题。我认为,这可能比将值写入持久性存储的性能更好——如果他使用来自可接受答案的SQL,那么随着数据的增长,触发器将非常慢,因为它不会限制对当前记录的更新。如果表被很好地索引了,并且没有荒谬的记录数,那么每次有人点击视图策略时,简单地运行查询应该可以正常工作。。。