MySql:使用联合或连接按计数选择

Posted

技术标签:

【中文标题】MySql:使用联合或连接按计数选择【英文标题】:MySql: Select by Count with Union or Joins 【发布时间】:2011-12-16 19:26:38 【问题描述】:

我需要一种方法让页面管理员查看他们页面的成员,这些成员按用户在该特定页面上的帖子总数排序。帖子存储在不同的表格中,例如投票、下载、wiki 等(如 15 个表格)。每个都有 id、user_id、page_id、title、content 等结构。列出页面所有用户的表称为“收藏夹”。它的结构就是 id, user_id, page_id, date。

我目前有一个查询,它将所有“内容表”联合在一起,以便特定用户在网站上显示他们关于它所在页面的所有帖子,我可以很容易地使用 WHERE 使其特定于每个页面page_id = $page_id)。我尝试使用该代码来执行我在版主区域中尝试执行的操作。正如我所提到的,在版主区域中,我需要按用户的总帖子数 DESC 对用户列表进行排序。

我有这个代码,但它不工作。

$getfans = mysql_query("SELECT DISTINCT user_id, ((SELECT id FROM wiki WHERE wiki.page_id = $page_id AND wiki.user_id = favorites.user_id)
UNION ALL
(SELECT id FROM downloads WHERE downloads.page_id = $page_id AND downloads.user_id = favorites.user_id)
UNION ALL
(SELECT id FROM polls WHERE polls.page_id = $page_id AND polls.user_id = favorites.user_id)) AS posts 
FROM favorites WHERE favorites.page_id = $page_id AND favorites.status = 0 ORDER BY posts DESC", $conn);

我尝试了其他同样无效的方法,但这个方法对我来说最合乎逻辑,所以我将只展示它

请帮忙。谢谢。

另外...

这也许是朝着正确方向迈出的一步

$getfans = mysql_query("SELECT DISTINCT user_id, (SELECT COUNT(id) FROM polls WHERE page_id = $page_id AND user_id = favorites.user_id) AS 来自收藏夹的帖子 WHERE favorites.page_id = $page_id AND favorites.status = 0 ORDER BY posts DESC", $conn);

当我回显 $posts 时,它为我提供了该页面用户投票的正确计数。

但是,当我尝试处理多个表时,它只返回了一个用户。

例子:

$getfans = mysql_query("SELECT DISTINCT user_id, SUM((SELECT COUNT(id) FROM polls WHERE page_id = $page_id AND user_id = favorites.user_id)+(SELECT COUNT(id) FROM wiki WHERE page_id = $page_id AND user_id = favorites.user_id)) 来自收藏夹的帖子 WHERE favorites.page_id = $page_id AND favorites.status = 0 ORDER BY 发布 DESC", $conn);

我找到了解决方案 如果好奇,请阅读我下面的帖子。

【问题讨论】:

你是在总结每个用户每个表中有多少行吗? 是的。而且我已经完成了各种方法,包括 COUNT(*) 和 * 但仍然没有奏效。当我只是想显示一个用户的所有帖子时,整个联合块本身就可以工作,但当我试图显示所有用户然后按帖子排序时却不行。 【参考方案1】:

使用左连接!

SELECT 
    f.user_id, 
    COUNT(w.user_id) + COUNT(d.user_id) + COUNT(p.user_id) as PageCount
FROM 
    favorites f
    left join wiki w on
        f.page_id = w.page_id
        and f.user_id = w.user_id
    left join downloads d on
        f.page_id = d.page_id
        and f.user_id = d.user_id
    left join polls p on
        f.page_id = p.page_id
        and f.user_id = p.user_id
WHERE 
    f.page_id = $page_id 
    AND f.status = 0
GROUP BY
    f.user_id
ORDER BY PageCount DESC

如果您想坚持联合方法:

select
    f.user_id,
    count(x.user_id) as PageCount
from
    favorites f
    inner join (
        select user_id, page_id from wiki
        union all
        select user_id, page_id from downloads
        union all
        select user_id, page_id from polls
        union all
        select user_id, page_id from videos
    ) x on
       f.user_id = x.user_id
       and f.page_id = x.page_id
WHERE 
    f.page_id = $page_id 
    AND f.status = 0
group by
    f.user_id
ORDER BY PageCount DESC

您想将group by 用于聚合,而count 函数将忽略您遇到的任何空值,因此它计算正匹配。

【讨论】:

嗯,我不确定这是否会令人愉快,因为我所拥有的表格不仅是我示例中的三个(民意调查、维基和下载),还有……视频、照片、演练、维基、评论、文章、新闻、争议、forums_posts、报价、测验……也许还有一些我错过的。我不明白我是否可以使用一个大型联合来计算所有这些,以便用户查看他们所有帖子的长列表,为什么我不能使用相同的计数来为他们的帖子排序? 添加了联合方法。不知道 MySQL,但 SQL Server 通常会优化这些谓词,因此您不会拉回很多东西。无论如何,您实际上不会看到左连接实例中的表,您只会使用它们来过滤您的查询。您将看到的唯一内容是您在子句的 select 部分中拉回的列。 另外,我刚刚尝试了您的代码,但没有成功。我还将 PageCount 更改为帖子,以查看是否是问题所在,但这也不起作用。 “没用”是什么意思?你期待看到什么结果却没有看到?还是您收到错误消息?您尝试了哪个代码——第一个还是第二个? AHHHHHHHH :) 只有一个变化。我不得不将 INNER JOIN 更改为 LEFT JOIN,因为我需要它来显示页面的所有用户,即使是那些有 0 个帖子的用户,而之前(使用内部连接)它只显示在其他表中有行的用户。感谢SSSSSSSS【参考方案2】:

我找到了解决方案。我以为我早点有这个,但我想我有点偏离了。感谢所有参与的人。

$getfans = mysql_query("SELECT DISTINCT user_id,
(SELECT COUNT(id) FROM wiki WHERE page_id = $page_id AND user_id = favorites.user_id) + 
(SELECT COUNT(id) FROM downloads WHERE page_id = $page_id AND user_id = favorites.user_id) + 
(SELECT COUNT(id) FROM polls WHERE page_id = $page_id AND user_id = favorites.user_id)  
AS posts FROM favorites
WHERE favorites.page_id = $page_id
AND favorites.status = 0
ORDER BY posts DESC", $conn);

只需继续在每个新表的末尾使用 + 进行子查询。也许不是最简洁的代码,但它确实有效。

这行得通。这两天我不能接受它作为答案:(

【讨论】:

删除DISTINCT并在ORDER BY之前添加GROUP BY user_id 是的,GROUP BY 会比 DISTINCT 快(但首先要检查它们是否产生相同的结果,我认为在这种情况下它们会这样做)。【参考方案3】:

这是我最喜欢的一个表的 SQL 查询,

Select Distinct user_id, Count(user_id) as C from yourtable group by user_id 

将向您显示每个人的 user_id 以及他们在该表中的行数。组合这些结果应该很简单。

顺便说一句,如果所有表都具有相同的结构,为什么不将它们都放在同一个表中?您可以添加一列来指示记录适用于哪种类型的项目。

【讨论】:

那样会非常混乱,因为结构不完全相同。 ...我不确定你写的内容将如何应用于我在示例中给出的 3 个表。你能进一步解释一下吗?在您的示例中实际使用我的表格? 我对你投了反对票有两个原因:(1) 当你有一个group by 时,你使用了一个不必要的distinct,(2) 你只展示了一个通用聚合而不是帮助用户解决他或她的问题。 不同的可能是我的错,因为我一直在尝试一切(有点像在这里拉稻草),有时当我继续我的下一次尝试时,有些事情在我的查询中徘徊不应该一直待在那里,直到我意识到并把它拿出来再试一次。他只是复制和粘贴。至于没有帮助,我同意。 你知道,埃里克,我多年来一直在使用该查询。我不确定是否需要 distinct。

以上是关于MySql:使用联合或连接按计数选择的主要内容,如果未能解决你的问题,请参考以下文章

SQL:联合或自加入

MySQL数据库联合查询与连接查询

使用联合第 2 部分从多个表中选择计数相关行

选择后的MySQL联合[重复]

mysql 联合查询

Mysql联合查询语句语法