mysql - 复杂(ish)连接问题:

标签 mysql sql join

我在 mySQL 数据库中有下表(注意:这些是总结的,因此它们与这个问题相关,一些列已被省略)。

author (id, username, password etc.)
thread (id, title, content)
tag (id, name)
reply (id, content)
thread_replies (thread_id, reply_id)
author_replies (author_id, reply_id)
thread_tags (thread_id, tag_id)
author_threads (author_id, thread_id)

现在要获取某个作者的帖子,我通常这样做:

SELECT thread.title, thread.id AS thread_id, thread.content, author.username, author.id AS author_id
FROM thread
JOIN author_threads ON thread.id = author_threads.thread_id
JOIN author ON author_threads.author_id = author.id
WHERE author.id = '12'

这工作正常,但是当我尝试获取与这些线程关联的标签时:

SELECT thread.title, thread.id AS thread_id, thread.content, author.username, author.id AS author_id, GROUP_CONCAT( DISTINCT tag.name
ORDER BY tag.name DESC
SEPARATOR ',' ) AS tags
FROM thread
JOIN thread_tags ON thread.id = thread_tags.thread_id
JOIN tag ON thread_tags.tag_id = tag.id
JOIN author_threads ON thread.id = author_threads.thread_id
JOIN author ON author_threads.author_id = author.id
WHERE author.id = '12'
LIMIT 0 , 30

它仅在一列中显示第一个线程以及与该作者关联的所有标签。

我在这里做错了什么?

另外,如果我想计算作者为每个主题获得的回复数量,该怎么做?

最佳答案

由于您在查询中使用聚合 (GROUP_CONCAT),因此您的查询将被分组。由于您没有 group by 子句,因此您的组是整个结果集(因此可以看到作者使用的每个标签)。由于 MySQL 允许在分组语句中使用非分组列,因此您不会收到错误,但不会获得所需的查询。

为了检索正确的结果,您需要根据 thread.id 对查询进行分组。

select
    thread.title, 
    thread.id as thread_id, 
    thread.content, 
    author.username, 
    author.id as author_id, 
    group_concat(distinct tag.name order by tag.name desc separator ',') as tags

from thread

join thread_tags ON thread.id = thread_tags.thread_id
join tag ON thread_tags.tag_id = tag.id
join author_threads ON thread.id = author_threads.thread_id
join author ON author_threads.author_id = author.id

where author.id = '12'

group by thread.id

limit 0 , 30

这应该在 MySQL 中工作,尽管它不是符合 ANSI 的 SQL,因为您在 select 子句中使用非分组列而不进行任何聚合。您可以保持原样,也可以编写更兼容的 SQL,并在除 thread.id 之外的所有列上使用诸如 max 之类的内容。这看起来不太漂亮,但它是合规的。

SELECT 
    max(thread.title) as title, 
    thread.id as thread_id, 
    max(thread.content) as content, 
    max(author.username) as username, 
    max(author.id) as author_id, 
    group_concat(distinct tag.name order by tag.name desc separator ',') as tags

from thread

join thread_tags ON thread.id = thread_tags.thread_id
join tag ON thread_tags.tag_id = tag.id
join author_threads ON thread.id = author_threads.thread_id
join author ON author_threads.author_id = author.id

where author.id = '12'

group by thread.id

LIMIT 0 , 30

回复计数

上述查询(以及您的原始查询)适合检索标签列表。您可以编写一个等效的查询来检索回复计数(假设回复不是嵌套的,在这种情况下,您必须使用 MySQL 提供的任何递归查询功能,我对此不熟悉),但要检索两者在单个查询中需要子查询:

select
    thread.title, 
    thread.id as thread_id, 
    thread.content, 
    author.username, 
    author.id, 
    (select group_concat(distinct tag.name order by tag.name separator ',')

    from thread_tags

    join tag on tag.id = thread_tags.tag_id 

    where thread_tags.thread_id = thread.id) as tags,
    (select count(1) from thread_replies where thread_id = thread.id) as reply_count

from thread

join author_threads ON thread.id = author_threads.thread_id
join author ON author_threads.author_id = author.id

where author.id = '12'

LIMIT 0 , 30

我已从此查询中删除了 group by,因为我们的聚合已移至子选择中,这意味着外部查询不再分组。

关于mysql - 复杂(ish)连接问题:,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5639172/

相关文章:

mysql - 如何在 SQL 中按最大日期分组(Order By a Group By)

mysql - Createddatetime 列填充为 0000-00-00

mysql - 连接两个 SQL 查询

sql - 有没有办法简化这个 TSQL Case 语句?

php - MySQL中SQL语句的问题

PHP MySQL 加入并输出为数组

php - 如何更新从组合框中获取的数据?

sql - 如何在 SQL Server Management Studio 中编辑多行/数据条目

MySQL 连接 3 个表的技巧

MySQL:从数据库中获取记录并向行添加 COUNT() 列