在标记方案中,Mysql count()未与两个表JOIN和GROUP BY求和
我有一个问题场景,这些问题都有与之相关联的标签,比如这里的StackOverflow。我想列出与某个问题相关联的所有标记,以及每个标记的计数,以说明其他问题使用/引用同一标记的次数 标签表:标签id、标签名称标签名称是唯一的 标记交叉引用表:标记id、问题id标记id引用标记表中的标记id,以及问题表中的问题id 问题表:问题id,问题 我的代码列出了与特定问题id关联的所有标记,但每个标记的总使用量的计数/数量始终为1,但应该是不同的总数在标记方案中,Mysql count()未与两个表JOIN和GROUP BY求和,mysql,sql,join,group-by,count,Mysql,Sql,Join,Group By,Count,我有一个问题场景,这些问题都有与之相关联的标签,比如这里的StackOverflow。我想列出与某个问题相关联的所有标记,以及每个标记的计数,以说明其他问题使用/引用同一标记的次数 标签表:标签id、标签名称标签名称是唯一的 标记交叉引用表:标记id、问题id标记id引用标记表中的标记id,以及问题表中的问题id 问题表:问题id,问题 我的代码列出了与特定问题id关联的所有标记,但每个标记的总使用量的计数/数量始终为1,但应该是不同的总数 $question_id = 268; $sql =
$question_id = 268;
$sql = 'SELECT tags.tag_id, tag_name, count(tags.tag_id) AS num
FROM tags LEFT JOIN tags_x
ON tags.tag_id = tags_x.tag_id
WHERE tags_x.question_id = ?
GROUP BY tags.tag_name';
$stmt = $db->prepare($sql);
$stmt->execute([$question_id]);
$result = $stmt->fetchAll(pdo::FETCH_ASSOC);
$out = '';
foreach($result as $row){
$tag_id = $row['tag_id'];
$tag_name = $row['tag_name'];
$num = $row['num'];//count of all items referencing same tagname
echo $tag_id.' - '.$tag_name.' - '.$num.'<br>';
}
当您在SELECT子句中包含tags.tag_id时,MySql将隐式地将其作为GROUP BY的一部分。这违反了ansi标准,顺便说一句,该标准根本不允许此查询
也许你想要counttags\u x.tag\u id
一个选项使用相关子查询来计算每个标记的问题数。我希望有更好的效率,因为它避免了外部聚合的需要:
select
t.tag_id,
t.tag_name,
(select count(*) from tags_x tx1 where tx1.tag_id = t.tag_id) no_questions
from tags t
inner join tags_x tx on tx.tag_id = t.tag_id
where tx.question_id = ?
这将为您提供每个标签的问题总数。如果要计算除当前问题之外的其他问题的计数,可以从结果中减去1,或优化子查询的where条件:
select
t.tag_id,
t.tag_name,
(select count(*) from tags_x tx1 where tx1.tag_id = t.tag_id and tx1.question_id <> tx.question_id) no_questions
from tags t
inner join tags_x tx on tx.tag_id = t.tag_id
where tx.question_id = ?
我认为我们需要两个对tag_x交叉引用表的引用,一个用于获取与我们的问题相关的标记,另一个用于获取对同一标记的所有引用
要返回标记名,我们需要一个到标记表的联接
大概是这样的:
SELECT t.tag_name
, t.tag_id
, COUNT(c.tag_id) AS cnt_references
FROM tags_x q
JOIN tags_x c
ON c.tag_id = t.tag_id
JOIN tags
ON t.tag_id = q.tag_id
WHERE q.question_id = ?
GROUP
BY t.tag_name
, t.tag_id
ORDER
BY t.tag_name
, t.tag_id
SELECT q.tag_id
, COUNT(c.tag_id) AS cnt_references
FROM tags_x q
JOIN tags_x c
ON c.tag_id = t.tag_id
WHERE q.question_id = ?
GROUP
BY q.tag_id
ORDER
BY q.tag_id
如果不需要返回tag_name,可以避免连接到tag表,只需执行以下操作:
SELECT t.tag_name
, t.tag_id
, COUNT(c.tag_id) AS cnt_references
FROM tags_x q
JOIN tags_x c
ON c.tag_id = t.tag_id
JOIN tags
ON t.tag_id = q.tag_id
WHERE q.question_id = ?
GROUP
BY t.tag_name
, t.tag_id
ORDER
BY t.tag_name
, t.tag_id
SELECT q.tag_id
, COUNT(c.tag_id) AS cnt_references
FROM tags_x q
JOIN tags_x c
ON c.tag_id = t.tag_id
WHERE q.question_id = ?
GROUP
BY q.tag_id
ORDER
BY q.tag_id
在内联视图中这样做可能会更快,稍后再连接到标记表。这将给出与第一个查询相同的结果
SELECT t.tag_name
, t.tag_id
, r.cnt_references
FROM ( -- inline view to count references, one row per tag_id
SELECT q.tag_id
, COUNT(c.tag_id) AS cnt_references
FROM tags_x q
JOIN tags_x c
ON c.tag_id = t.tag_id
WHERE q.question_id = ?
GROUP
BY q.tag_id
) r
JOIN tags t
ON t.tag_id = r.tag_id
ORDER
BY t.tag_name
, t.tag_id
尝试了上面的代码修改,得到了同样的结果。顶级代码工作得非常好!子查询-不知道您可以这样做!非常感谢你!