如何计算每一行的连接中的所有实例?
Posted
技术标签:
【中文标题】如何计算每一行的连接中的所有实例?【英文标题】:How to count all instance in the join for each row? 【发布时间】:2012-12-10 00:02:01 【问题描述】:我有以下方案:
CREATE TABLE IF NOT EXISTS `answers` (
`id` bigint(20) unsigned NOT NULL,
`answer` varchar(200) NOT NULL,
`username` varchar(15) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`,`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `answers` (`id`, `answer`, `username`, `date`) VALUES
(1, 'gfdsf', 'guy', '2012-12-22 00:00:00'),
(4, 'gfdddsfs', 'maricela', '2012-12-22 00:00:00'),
(4, 'gfddsfs', 'mikha', '2012-12-22 00:00:00'),
(4, 'gfdsfs', 'guy', '2012-12-22 00:00:00');
CREATE TABLE IF NOT EXISTS `questions` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`asker_username` varchar(15) NOT NULL,
`target_username` varchar(15) NOT NULL,
`question` varchar(200) NOT NULL,
`hide` enum('y','n') NOT NULL DEFAULT 'n',
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `questions` (`id`, `asker_username`, `target_username`, `question`, `date`) VALUES
(1, 'mikha', 'guy', 'testo festo', '2012-12-22 00:00:00'),
(2, 'mikha', 'guy', 'saaaaaaaar', '2012-12-22 00:00:00'),
(3, 'sys.tem', 'every.one', 'test g1', '2012-12-06 00:00:00'),
(4, 'sys.tem', 'every.one', 'test g2', '2012-12-06 00:00:00');
我使用以下查询:
SELECT
questions.id AS questionid,
COUNT(answers.username) AS count_everyone,
answers.username
FROM questions
LEFT JOIN answers ON questions.id = answers.id
GROUP BY questions.id,answers.username
问题在于COUNT(answers.username
。我想计算每个问题的答案,但查询显示计数为 1。例如,问题 ID 4 被回答 3 次,但 COUNT(answers.username)
将其显示为 1 而不是 3。
这是预期的结果:
questionid count_everyone username
1 1 guy
2 0 null
3 0 null
4 3 guy
4 3 maricela
4 3 mikha
这是我实际得到的结果:
questionid count_everyone username
1 1 guy
2 0 null
3 0 null
4 1 guy
4 1 maricela
4 1 mikha
谢谢
【问题讨论】:
既然您是按用户名分组的,为什么您希望每一行有多个用户名? 如果我删除用户名分组,只会显示一个答案。我想同时显示所有答案及其计数...谢谢:) maricela 只回答了第 4 题一次,那你为什么期望计数是 3? 问题编号由3个人回答..所以答案的数量应该是3而不是1......同一个人不能多次回答同一个问题..恰恰相反。 .一个问题可以由不同的人回答 但是当您在 GROUP BY 子句中包含用户名时,您并没有计算所有人,您只是计算了一个用户。为什么每个用户名的行对其他人都有计数?也许您应该使用 GROUP_CONCAT 列出行中的所有用户名,而不是为每个用户名单独一行? 【参考方案1】:select q.id, coalesce(j.AnswerCount, 0) as AnswerCount, a.username
from questions q
left outer join
(select id as Qid, count(answer) as AnswerCount
from answers
group by id) j
on q.id = j.Qid
left outer join
answers a on q.id = a.id
【讨论】:
我认为子查询在大规模上表现不佳。没有子查询还有其他方法吗?谢谢:) 如果你想要上面指出的答案,你必须先对每个问题做一个 COUNT。为什么不先尝试一下,然后再决定如何扩展? 我这里有很多解决方案...我只是担心...无论如何我还没有测试...感谢您的回答:) +1 这是另一种写法。但是你需要一个 IFNULL 来匹配 OP 想要的结果集。 sqlfiddle.com/#!2/73ff3/26 我正在给你上面要求的答案。顺便说一句,这不是一项昂贵的操作。即使您发现了一些语法技巧,系统也必须计算每个问题的所有答案,否则它如何计算出“3”?如果您担心性能,请确定您是否真的需要您指定的输出。【参考方案2】:要获得正确的计数,您应该只按问题 ID 分组,而不是用户名:
SELECT
questions.id AS questionid,
COUNT(answers.username) AS count_everyone
FROM questions
LEFT JOIN answers ON questions.id = answers.id
GROUP BY questions.id
如果您有在同一查询中获取用户名,请使用连接:
SELECT questionid, count_everyone, username
FROM
(
SELECT
questions.id AS questionid,
COUNT(answers.username) AS count_everyone
FROM questions
LEFT JOIN answers ON questions.id = answers.id
GROUP BY questions.id
) T1
LEFT JOIN answers ON T1.questionid = answers.id
sqlfiddle
或GROUP_CONCAT
:
SELECT
questions.id AS questionid,
COUNT(answers.username) AS count_everyone,
GROUP_CONCAT(answers.username) AS usernames
FROM questions
LEFT JOIN answers ON questions.id = answers.id
GROUP BY questions.id
sqlfiddle
或相关子查询:
SELECT
questions.id AS questionid,
(SELECT COUNT(*) FROM answers WHERE questions.id = answers.id) AS count_everyone,
answers.username
FROM questions
LEFT JOIN answers ON questions.id = answers.id
sqlfiddle
【讨论】:
+1,但我认为count
的参数不应该是“用户名”。据我了解这个问题,回答的人是否有用户名并不重要。
如果我只按问题ID分组,只会显示1个答案:)
仅当questions.target_username
等于every.one
时才需要此计数,而不是所有问题。因此,您是否建议在单独的查询中进行更多操作,因为它是偶尔的??
@a1ex07:根据answers.username
不可为空,因此您对没有用户名的用户的担忧似乎与此无关。我认为COUNT
的论点很好。
@MichaelSamuel:结果集对于人类来说很难阅读。多次重复计数会令人困惑。在将结果显示给用户之前,您必须以更合乎逻辑的方式重新格式化您的结果。但是,为您的结果集编写解析器也可能会很麻烦。你试过了吗?您可能需要在迭代时记住上一个问题 ID。所以……你有一个复杂的 SQL 查询和一个复杂的解析器来读取结果,你甚至不知道你是否获得了性能优势……值得吗?【参考方案3】:
这个怎么样:
SELECT
questions.id AS questionid,
COUNT(answers.username) AS count_everyone,
GROUP_CONCAT(answers.username) users
FROM questions
LEFT JOIN answers ON questions.id = answers.id
WHERE questions.target_username = 'every.one'
GROUP BY questions.id
FIDDLE
【讨论】:
马克已经发布了这个解决方案。我可以这样工作,但我需要单独的每一行而不是这样组合。无论如何,我都在考虑给答案一个独特的自动增量,因为我认为这在大规模上会更好..谢谢@Barmar :) 如果你真的需要每一个单独的行,那么 ExactaBox 的答案就是你应该使用的。【参考方案4】:编辑
我想你正在寻找这个,它会显示所有问题 id 并计算所有答案,并显示所有用户名。
DEMO SLQFIDDLE
【讨论】:
如果您查看方案中的第 4 个问题,您会发现它实际上是由 3 个人回答的 :) 我需要按questions.id
分组,因为即使没有回答,我也想显示问题。
再次仅按questions.id
分组不会显示所有答案:我想显示所有答案及其数量:)
再次,这仅显示一次问题:D 我想在单独的行中显示所有答案并计算每个问题的所有答案..谢谢 :)
我不知道你对我投了反对票,因为我给了你正确的答案
我不知道是谁干的...对不起...不是我...谢谢你的回答@goodmood :)【参考方案5】:
据我所知,你应该改变这个:
COUNT(answers.username) AS count_everyone,
到:
COUNT(answers.id) AS count_everyone,
因为您实际上想计算具有相同 ID 的答案的数量...
【讨论】:
两者都给出相同的结果 :)answers.username
也是独一无二的,所以无论是这个还是这个......谢谢
我的错,因为您按用户名分组,这不会改变任何事情:S以上是关于如何计算每一行的连接中的所有实例?的主要内容,如果未能解决你的问题,请参考以下文章
mysql连接具有相同列值的两行并计算某些列值并返回一行中的所有行
Arduino与Proteus仿真实例-4x4矩阵键盘驱动仿真