我有一个与标签相关联的问题,例如此处的StackOverflow。我想列出与某个问题相关的所有标签,以及每个标签的计数,以告诉其他问题使用/引用同一标签多少次。
TAGS TABLE: tag_id,标记名(标记名是唯一的)
标签交叉引用表:tag_id,question_id(tag_id在标签表中引用tag_id,在问题表中引用question_id)。
QUESTONS TABLE:问题ID,问题。
我拥有的代码列出了与特定Question_id相关联的所有标签,但是每个标签的总使用次数的count()/ num始终为“ 1”,但应总计不同的数字...
$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
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 = ?
当您在tags.tag_id
子句中包含SELECT
时,MySql会将其隐式包括在GROUP BY
中。这违反了ansi标准btw,后者根本不允许该查询。
也许您想要count(tags_x.tag_id)
。
SELECT tags.tag_id, tag_name, count(tags_x.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_id, tags.tag_name
我认为我们需要对tag_x
交叉引用表的two引用,一个需要获取与我们的问题相关的标签,另一个需要all引用相同的标签。
要返回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
如果不需要返回tag_name
,我们可以避免联接到tag
表,而只需执行以下操作:
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
表。这应该与第一个查询给出等效的结果。
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