如何加入一对多的关系

时间:2013-02-22 21:28:58

标签: sql join

我正在尝试加入3个表... months,monthly_results和issue_results。每月只有一个月度结果记录,但每月0到n个issue_results。当没有Issue_results时,我可以设置一个Left Join来获取Month_results。我的问题是我一个月内有多个issue_results。我只希望在我的结果集中出现一次month_results ...否则我们会在报告每月总计时重复计算结果。

例如,这是表格

月1,2,3

每月结果(月份,份数)
(1,5000)
(2,2500)
(3,1000)

发布结果(问题,月份,订单)
(1,1,750)
(2,1,500)
(3,3,250)

当我加入表格时,我希望看到以下内容:

(月,期,副本,订单)
1,1,5000,750
1,2,5,500 2,,2500,
3,3,1000,250

使用左外连接我可以获得第二个月(没有正确填充的问题),但不幸的是,我在第二个月获得了以下重复的每月结果1 ...

1,1,5000,750
1,2, 5000 ,500
2,,2500,
3,3,1000,250

非常感谢任何和所有建议。

2 个答案:

答案 0 :(得分:1)

在给定的表格中没有足够的信息来确定5000个副本与之关联的第1个月的哪个问题。您要查找的结果显示与问题1相关的5000个副本而不是问题2,但表中没有任何信息可以进行区分。澄清:

包含有关第1个月的信息的表格行如下:

每月结果:

    (Month, Copies)
    (1,5000)

问题结果:

    (Issue, Month, Orders)
    (1,1,750)
    (2,1,500)

通过这种方式来看,您可以从“每月结果”表中看到,与5000份副本相关的唯一信息是第1个月。因此,当您加入“发布结果”时,这两个问题在第1个月匹配5000份。

要获得您正在寻找的结果,请:

1)您的第一张表需要包括问题(月份,问题,副本)
2)或者你需要说明你如何选择“获得”副本的问题(如果每月有> 1个问题)。 sgeddes提供了一个很好的解决方案,本月的第一期是获得副本的问题。

答案 1 :(得分:0)

根据您的RDBMS,有不同的方法来实现这一目标。

这是一个MySQL解决方案:

SELECT M.Month, 
  I.Issue,
  @copies:=IF(@prevMonth=M.Month,NULL,M.Copies) copies,
  I.Orders,
  @prevMonth:=M.Month
FROM MonthResults M
  LEFT JOIN IssueResults I ON M.Month = I.Month
  JOIN (SELECT @copies:=0) t;

Sample Fiddle Demo

这是一种更通用的方法,适用于大多数RDBMS:

SELECT M.Month, 
  I.Issue,
  T.Copies,
  I.Orders
FROM MonthResults M
  LEFT JOIN IssueResults I ON M.Month = I.Month
  LEFT JOIN (
      SELECT Min(I.Issue) minIssue,
        M.Month, M.Copies
      FROM MonthResults M LEFT JOIN IssueResults I ON M.Month=I.Month
      GROUP BY M.Month, M.Copies
) t ON M.Month = t.Month AND (I.Issue = t.minIssue OR I.Issue IS NULL)

And another Fiddle demo