【问题标题】:one to many relationship - one item with many comments一对多关系 - 一项有很多评论
【发布时间】:2012-01-24 19:50:07
【问题描述】:

我正在尝试提取存在于几个不同表中的数据。具体来说,我有一个错误表,还有一个关于这些错误的“帖子”(cmets/updates)表。对于每个错误,可能没有 cmets、一个注释或多个。我希望返回所有错误,并返回所有 cmets(虽然我想省略更新),但作为列,而不是每个错误/评论一行。

这是我开始的地方:

select 
b.bg_id,
b.bg_reported_date as "Date Created",
b.bg_short_desc as "Summary",
bp.bp_comment_search as "Comment Body", 
s.st_name as "Status",
p.pr_name as "Priority",
bp.bp_type as "Update Type"
from 
bugs b
inner join bug_posts bp on b.bg_id = bp.bp_bug
inner join statuses s on b.bg_status = s.st_id
inner join priorities p on b.bg_priority = p.pr_id
--where bp.bp_type = 'comment'
order by b.bg_id asc

这给了我每条评论一行,这不是我想要的。如您所见,我还尝试将结果限制为仅包含“评论”类型的帖子,但这排除了任何没有 cmets 的错误,因此我将其删除。

我发现这篇文章似乎相关:JOIN in SQL with one-to-many relationship

但我无法让它与我的查询一起使用。这是我目前所拥有的:

select 
b.bg_id,
b.bg_reported_date as "Date Created",
b.bg_short_desc as "Summary",
--bp.bp_comment_search as "Comment Body", 
s.st_name as "Status",
p.pr_name as "Priority",
--bp.bp_type as "Update Type"
from
bugs b
left outer join
    (select bp_comment_search as "Comment Body"
    from bug_posts
    group by bp_bug) bp on bp.bp_bug = b.bg_id
--inner join bug_posts bp on b.bg_id = bp.bp_bug

inner join statuses s on b.bg_status = s.st_id
inner join priorities p on b.bg_priority = p.pr_id
--where bp.bp_type = 'comment'
order by b.bg_id asc

我的 SQL 知识非常有限,但任何人都可以提供任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 您使用的是哪种 SQL(MySQL、Postgres、Oracle、MSSql)以及它的哪个版本?
  • 我在下面的答案中添加了一个示例。将 cmets 放入列(而不是行)的部分 -> 为什么要这样做?你能举一个期望输出的例子吗?

标签: sql sql-server-2008 one-to-many


【解决方案1】:

您应该将过滤器保留为“仅 cmets”,但将“INNER JOIN”更改为“LEFT JOIN”,然后您将看到所有错误天气或没有 cmets。

您正在寻找的另一个函数称为“pivot”,它将(cmets 的)行遍历到列中。

我自己不了解 SQL Server 2008,但找到了此链接: directly to microsoft.

所以,除了 'cmets to columns' 操作之外,这可能是您的查询:

select 
b.bg_id,
b.bg_reported_date as "Date Created",
b.bg_short_desc as "Summary",
bp.bp_comment_search as "Comment Body", 
s.st_name as "Status",
p.pr_name as "Priority",
from
bugs b
left join bug_posts bp on b.bg_id = bp.bp_bug AND bp.bp_type = 'comment'
inner join statuses s on b.bg_status = s.st_id
inner join priorities p on b.bg_priority = p.pr_id
order by b.bg_id asc

【讨论】:

  • 我希望将 cmets 作为列而不是行,因为我打算将其导出为 excel (CSV),然后将其导入另一个工具 (JIRA)。该工具期望每条评论为一列,而每条错误仅为一行。那有意义吗?如果没有,我会添加我希望看到的示例。
  • 我怀疑 PIVOT 对于这个问题充其量是粗鲁的矫枉过正,最坏的情况是根本无法解决它。您建议我们使用什么作为枢轴键,不会导致每个评论都有自己的一组列?大概您需要为每个评论分配一个相对于由错误键定义的组的序列号。这可能是可以做到的,但是更大的问题仍然存在:当您可以处理评论行时为什么要这样做?
  • @user1108721 正如 sacundim 指出的那样,这有点像“坏主意”。您要么必须牺牲 cmets(如果太多),要么一直有空列(如果太少)。我建议您使用我的示例并以您的编程语言手动将 cmets 打包到 CSV。
【解决方案2】:

对于每个错误,可能没有 cmets、一个注释或多个。我希望返回所有错误,并返回所有 cmets(虽然我想省略更新),但作为列,而不是每个错误/评论一行。

对于任意数量的 cmets 无法做到这一点。这将要求您的查询根据数据返回可变数量的列,但在 SQL 中,结果集中的列数完全由查询和表定义决定。

您需要为每个评论提取一行(来自与您类似的查询,或者来自仅提取评论数据的查询),并将每个评论数据行手动添加到代表其错误的对象. (大多数对象-关系映射器都以这种方式处理一对多关系,顺便说一句。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多