【问题标题】:JOIN Query with COUNT and WHERE in MySQL在 MySQL 中使用 COUNT 和 WHERE 连接查询
【发布时间】:2015-09-22 17:48:29
【问题描述】:

我正在尝试加入三个查询、2 个表和一个计数,连接本身工作正常:

SELECT * FROM `AccountInfo` NATURAL JOIN `userStats` WHERE `username` = 'x'

我想加入:

SELECT COUNT(following) FROM `followers` WHERE `following` = 'x'

为了获得关注特定用户的关注者数量,但我无法让加入工作。有什么想法吗?

 Account info:

|username|firstname|sirname |address |postcode|
|--------|-------- |--------|--------|--------|
| user1  | first   | last   |road A  |  1234  |
| user2  | name2   | last2  |road b  |  4567  |
|        |         |        |        |        |
|        |         |        |        |        |


  userStats

    |username|followers|following|lastseen |reputation|
    |--------|-------- |-------- |-------- |--------  |
    |  user1 |         |         |DD:MM:YY |  120     |
    |  user2 |         |         | DD:MM:YY|  130    |
    |        |         |         |         |          |
    |        |         |         |         |          |


followers

        |follower|following|
        |--------|-------- |
        |  user1 | user 2  | 
        |  user2 | user 1  | 
        |  user1 | user 3  | 
        |        |         | 

自然加入成功附加了 accountInfo 和 userStats 但我还想计算用户拥有的关注者数量,即用户名出现在“关注”列中的次数,以及他关注的用户数量,即用户名出现在“关注者”中的次数。 (虽然我没有问后半部分)

对于示例数据,它将显示:关注 = 2 和关注者 = 1

我不介意数据是否出现在连接表末尾的单独列中,但理想情况下会代替 userStats 表中的以下/关注者数据

【问题讨论】:

  • usernamefollowers 表中的其他字段是否可以加入?现在你的第二个查询只输出一个数字,但没有usernameid 或其他东西加入你的第一个查询,它只是一个总数。表架构或至少三个表的字段列表对我们帮助您最有帮助。
  • 是的,userStats 中有一个关注者字段,我感觉这可能需要一个 INNERJOIN 但不太确定如何去做.. 或者可能是“SELECT COUNT(following) AS xyz”并将其连接到最后(不太理想的选项)
  • 请分享您的表格结构、一些示例数据以及您想要获得的结果。
  • 已对其进行编辑以包含我正在寻找的内容
  • 不清楚你想要什么。表 userStats 中的列关注者和关注者的作用是什么?如果它们是下表中的计数,那么为什么要显示空白?哪个是“连接表”? (第一个查询结果?)“取代userStats表中的following/followers数据”是什么意思? (更新表 usersStats 以从表关注者中计算计数?从表 userStats 中删除关注者和关注者并将它们放在查询结果中?)请显示示例输入表和所需的输出表。

标签: mysql join count


【解决方案1】:

尚不清楚您的输入和期望的输出,但假设我们有以下谓词(参数化语句):

// user `username` named `firstname` `surname` lives at ...
// == `AccountInfo`(`username`,`firstname`,`surname`,...)

// user `username` was last seen at `lastseen` and ...
// == `userStats`(`username`,`lastseen`,...)

// user `follower` follows user `following`
// == `followers`(`follower`,`following`)

(我的userStats 没有followersfollowing 计数列。)

在每个谓词(参数化语句)之后,我为它写了一个简写。每个速记就像SQL CREATE TABLE。一个表(基础或查询结果)包含从其谓词构成一个真实命题(陈述)的行。

(我的回答继续在您的问题中使用NATURAL JOIN。)

满足两个基表谓词 AND 的行表是它们表的 NATURAL JOIN

//     user `username` named `firstname` `surname` lives at ...
// AND user `username` was last seen at `lastseen` and ...
// ==   `AccountInfo`(`username`,`firstname`,`surname`,...)
// AND `userStats`(`username`,`lastseen`,...)
SELECT * FROM `AccountInfo` NATURAL JOIN `userStats`

满足基表谓词和条件AND的行是基表WHERE条件:

//     `AccountInfo`(`username`,`firstname`,`surname`,...)
// AND `userStats`(`username`,`lastseen`,...)
// AND `username` = 'x'
SELECT * FROM `AccountInfo` NATURAL JOIN `userStats` WHERE `username` = 'x'

现在每个用户的关注者和关注者都很重要:

// user `username` follows user `following`
// == `followers`(`username`,`following`)
SELECT `follower` AS `username` FROM `followers`

// user `username` follows `followers` users
CREATE TABLE `nfollowing`
SELECT `follower` AS `username`, COUNT(`following`) AS following
FROM followers
GROUP BY `follower`

//    user `username` has follower `follower`
// == user `follower` follows user `username`
// == followers(`follower`,`username`)
SELECT `following` AS `username` FROM `followers`

// user `username` has `followers` followers
CREATE TABLE `nfollowers`
SELECT `following` AS `username`, COUNT(`follower`) AS followers
FROM followers
GROUP BY `following`

我们想要满足这些谓词的 AND 的行,即它们的表的 NATURAL JOIN 中的行:

// user `username` has `followers` followers and follows `following` users
// ==  user `username` has `followers` followers
// AND user `username` follows `following` users
CREATE TABLE `nfollow`
SELECT * FROM `nfollowers` NATURAL JOIN `nfollowing`

现在你的 userStats 是:

SELECT * FROM `userStats` NATURAL JOIN `nfollow`

您想要的查询可能是:

SELECT * FROM
   `AccountInfo` NATURAL JOIN `userStats` NATURAL JOIN `nfollow`
WHERE `username` = 'x'

【讨论】:

  • 感谢您的解释
  • 这有错误我会修复:nfollowX 谓词应该是“...and followX > 0”并且(因此)其他表达式没有 followX = 0 的行。
【解决方案2】:

给定以下数据:

CREATE TABLE `accountInfo` (
  `username` varchar(255) DEFAULT NULL,
  `firstname` varchar(255) DEFAULT NULL,
  `sirname` varchar(64) DEFAULT NULL,
  `address` varchar(64) DEFAULT NULL,
  `postcode` varchar(64) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `userstats` (
  `username` varchar(255) DEFAULT NULL,
  `followers` varchar(255) DEFAULT NULL,
  `following` varchar(64) DEFAULT NULL,
  `lastseen` date DEFAULT NULL,
  `reputation` int(64) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `followers` (
  `follower` varchar(255) DEFAULT NULL,
  `following` varchar(64) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `accountInfo` (`username`, `firstname`, `sirname`, `address`, `postcode`)
VALUES
    ('user1', 'first', 'last', 'road a', '1234'),
    ('user2', 'name2', 'last2', 'road b', '4567'),
    ('user3', 'name3', 'last3', 'road c', '8974');


INSERT INTO `userstats` (`username`, `followers`, `following`, `lastseen`, `reputation`)
VALUES
    ('user1', NULL, NULL, '2015-09-22', 120),
    ('user2', NULL, NULL, '2015-09-21', 130),
    ('user3', NULL, NULL, '2015-09-20', 80);

INSERT INTO `followers` (`follower`, `following`)VALUES
('user1', 'user2'),
('user2', 'user1'),
('user1', 'user3');

这些查询将给出用户的关注者数量或关注用户的数量:

select a.*, u.*, count(*) as number_following
from accountinfo a
    left join userstats u on(a.username = u.username)
    left join followers f1 on (u.username = f1.follower)
where 1
group by f1.follower;

select a.*, u.*, count(*) as number_of_followers
from accountinfo a
    left join userstats u on(a.username = u.username)
    left join followers f1 on (u.username = f1.following)
where 1
group by f1.following;

(2015 年 9 月 26 日更新) 您可以在左连接中使用子查询与 group by 来提取计数,例如:

    select a.*, u.*, f1.*, f2.*
   from accountinfo a
        left join userstats u on(a.username = u.username)
        left join (select f.follower as username, count(*) as following_count from followers f group by f.follower) f1 on (u.username = f1.username)
        left join (select f.following as username, count(*) as followers_count from followers f group by f.following) f2 on (u.username = f2.username)
    where 1;

【讨论】:

  • 非常感谢它的工作原理!.. 我非常有信心,读完这篇文章后我明白它是如何工作的,但你介意解释一下细节。我问是因为我注意到如果我搜索的用户名的关注者为零(未出现在关注者列中),number_following 返回的结果为 1 而不是 0。
  • @philipxy 我的意思是,即使对于名称未出现在 follower.follower 中的用户“userX”,对于上述表 f1,查询也会返回 1 而不是 0
  • @ J. R. & @vitamike 如果用户没有 u.followX,则使用 f1 左连接会给出该用户的一行和 NULL u.followX。 GROUP BY 为每个用户创建一组 1 行。 COUNT(*) 包含 NULL,因此为这些用户提供 1。您想要COUNT(f1.followX),因为列的COUNT 不计算NULL。 PS WHERE 1 不需要。
  • @vitamike 我关于 0 vs NULL 的评论与您关于 1 vs 0 的评论无关。(但我的评论实际上是关于 userStats 而不是这些查询。)
  • @philipxy 我编辑了我的答案以添加另一个查询,该查询仅计算关注者表中的行数,而不是 userX 的计数为 1
猜你喜欢
  • 1970-01-01
  • 2019-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2011-11-25
相关资源
最近更新 更多