Mysql 3 个表,多个计数分组依据,但卡住了

Mysql 3 tables, multiple counts grouped by, but gets stuck

我 运行 在查询时遇到了一些麻烦。我正在尝试检索涉及 3 table 的大型数据库的一些数据。

这些 tables 包含有关添加的数据,在后端网站中,管理员可以管理他想要显示的本地添加、位置等...这些组织在 3 tables,其中 1 个包含与添加信息相关的所有数据(名称、可用性日期、到期日期等...)。然后,还有另外 2 个 table 包含一些额外信息,但仅与浏览量或点击量有关。

所以我只有 15 个添加,有多次点击和多次查看。 每次点击并查看 table,为每次点击注册一个新行。因此,当点击被注册时,它会添加一个新行,其中 addid_views 是一个 register(click),addid 是来自 adds_table 的 addid。因此,例如,添加 (1) 将有 2 次查看和 2 次点击,而添加 (2) 将有 1 次查看和 1 次点击。

我的想法是获取每次添加的总点击次数和浏览次数。

我有 3 个这样的 table:

         adds_table           adds_clicks_table        adds_views_table
    +-------+-----------+   +-------------+------+     +-------------+------+  
    | addid | name      |   | addid_click |addid |     | addid_views |addid |
    +-------+-----------+   +-------------+------+     +-------------+------+
    | 1     | add_name1 |   | 1           | 1    |     | 1           | 1    |
    +-------+-----------+   +-------------+------+     +-------------+------+
    | 2     | add_name2 |   | 2           | 2    |     | 2           | 1    |
    +-------+-----------+
    | 3     | add_name3 |   | 3           | 1    |     | 3           | 2    |
    +-------+-----------+   +-------------+------+     +-------------+------+


CREATE TABLE `bwm_adds` (
  `addid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  ...
  PRIMARY KEY (`addid`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8

CREATE TABLE `bwm_adds_clicks` (
  `add_clickid` int(19) NOT NULL AUTO_INCREMENT,
  `addid` int(11) NOT NULL,
  ...
  PRIMARY KEY (`add_clickid`)
) ENGINE=InnoDB AUTO_INCREMENT=3374 DEFAULT CHARSET=utf8


CREATE TABLE `bwm_adds_views` (
  `add_viewsid` int(19) NOT NULL AUTO_INCREMENT,
  `addid` int(11) NOT NULL,
  ...
  PRIMARY KEY (`add_viewsid`)
) ENGINE=InnoDB AUTO_INCREMENT=2078738 DEFAULT CHARSET=utf8

结果将是一个 table,我在其中检索了每个添加 (addid) 的点击次数和浏览次数。

我需要得到所有查询,我得到这样的东西:

+-------+---------+-----------+
| addid | clicks  | views     |
+-------+---------+-----------+
| 1     | 123123  | 235457568 |
+-------+---------+-----------+
| 2     | 5124123 | 435345234 |
+-------+---------+-----------+
| 3     | 123541  | 453563623 |
+-------+---------+-----------+

我尝试执行一个查询,但它卡住了并加载了未定义的时间...我很确定我的查询失败了,因为如果我删除其中一个计数,会非常快速地显示一些数据。

SELECT a.addid, COUNT(ac.addid_clicks) as 'clicks', COUNT(av.addid_views) as 'views'
        FROM `adds_table` a 
        LEFT JOIN `adds_clicks_table` ac ON a.addid = ac.addid_click
        LEFT JOIN `adds_views_table` av ON ac.addid_click = av.addid_views
                GROUP BY a.addid

Mysql 一直在加载,有什么想法可以帮助我了解我缺少的内容吗?

顺便说一下,我发现 那里几乎解决了我遇到的相同问题,你可以看到我的查询与第一个答案非常相似,但是我一直收到正在加载消息。没有错误,只是正在加载。

编辑: 我把数字放错地方了,弄糊涂了。现在 tables 是固定的,我添加了一些解释。

Edit2: 我用 SHOW CREATE TABLES DEFINITIONS 更新了 post。

Edit3: 有什么办法可以优化这个查询吗?它似乎检索到我想要的结果,但 mysql 数据库取消了查询,因为它执行时间超过 30 秒。

SELECT a.addid,
       (SELECT COUNT(addid) FROM add_clicks where addid =  a.addid) as clicks,
       (SELECT COUNT(addid) FROM add_views  where addid =  a.addid) as views
    FROM adds a ORDER BY a.addid;

如果你有旧版本,

        SELECT  a.addid, 
                ( SELECT  COUNT(addid_clicks)
                    FROM  `adds_clicks_table`
                    WHERE  addid = a.addid 
                ) AS 'clicks', 
                ( SELECT  COUNT(addid_clicks)
                    FROM  `adds_views_table`
                    WHERE  addid = a.addid 
                ) AS 'views'
            FROM  adds_table AS a

对于 5.6 及更高版本,这可能会更快:

SELECT  a.addid, c.clicks, v.views
    FROM  `adds_table` a
    LEFT JOIN ( SELECT addid, COUNT(addid_clicks) FROM addid_clicks ) AS c USING(addid)
    LEFT JOIN ( SELECT addid, COUNT(addid_views)  FROM addid_views )  AS v USING(addid)

如果您得到 NULLs 但更喜欢 0s,则将值包装在 IFNULL(..., 0).

如需进一步讨论,请提供SHOW CREATE TABLEEXPLAIN SELECT ...

如果这些确实是您的表(一列,加上一个 auto_inc),则没有任何有意义的信息证明有 3 个表而不是 1 个:

CREATE TABLE `bwm_adds` (
  `addid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  clicks INT UNSIGNED NOT NULL,
  views  INT UNSIGNED NOT NULL,
  PRIMARY KEY (`addid`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8

然后 UPDATE ... SET views = views + 1(等)而不是插入到其他表中。

我最终找到了问题的解决方案。我试图达到的 table 是工程数据库设计错误的一个很大原因,在 adds_views_table 中,对于每个视图,都会添加一个新行。以近 300 万行结尾,table 几乎占整个数据库的 35% (326MB)。

当 phpmyadmin 尝试执行查询时,永远加载并且从未显示结果,因为 mysql 应用了超时限制。更改此值会有所帮助,但无法检索该数据并将其显示在网站上(这意味着在执行查询之前不会加载网站或数据)。

由于在 adds_table 中创建了 addid 索引,该问题已得到解决。此外,如果出于某种原因使用子查询,查询速度会更快。查询结束是这样的:

SELECT a.addid,
(SELECT COUNT(addid) FROM adds_clicks_table WHERE addid = a.addid) AS 'clicks',(SELECT COUNT(addid) FROM adds_views_table WHERE addid = a.addid) AS 'views'
FROM adds_table a
ORDER BY a.addid;

感谢 @Rick James 发布了类似的查询,我结束了修改它以获取我需要的数据

原谅我糟糕的英语