在标记方案中,Mysql count()不与两个表JOIN和GROPU BY求和

问题描述 投票:0回答:3

我有一个与标签相关联的问题,例如此处的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>';
}
mysql sql join group-by count
3个回答
0
投票

一个选项使用相关子查询来计算每个标签的问题数。我希望效率更高,因为它避免了外部聚合的需要:

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 = ? 

0
投票

当您在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

0
投票

我认为我们需要对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
© www.soinside.com 2019 - 2024. All rights reserved.