4

我有一个表,其中记录了服务器的停机时间。
我在 sqlfiddle 创建了这个表的简化版本。请看这里sqlfiddle
表有每条记录

Reason  Month   Down_Time
A       May     2
A       May     5
B       May     5
C       July    15
A       July    3
B       June    6
A       June    8
C       June    2

如果没有匹配的记录,我需要编写一个查询来获取给月和原因的所有组合与 NULL
例如:如果我需要获取系统在 5 月、6 月和 7 月由于原因 A、B 的停机时间或 D.. 我期待的是..

Reason  Month   DOWNTIME
A       May     7
A       June    8
A       July    3
B       May     5
B       June    6
B       July    NULL
D       May     NULL
D       June    NULL
D       July    NULL

由于我们在给定月份的记录中没有 D,它应该是 NULL
这是我的查询:

 SELECT Reasons.reason, Months.Month,sum( a.Down_time ) AS downtime
 FROM tabledown a
 RIGHT JOIN (
 SELECT 'A' AS reason
 UNION ALL SELECT 'B' AS reason
 UNION ALL SELECT 'D' AS reason
 ) Reasons
  ON a.reason = Reasons.reason
 RIGHT JOIN (
 SELECT 'May' AS month
  UNION ALL SELECT 'June' AS month
  UNION ALL SELECT 'July' AS month
 ) Months
 ON a.Month = Months.month
 GROUP BY Reasons.reason,Months.month
 ORDER BY Reasons.reason

为什么我没有得到预期的输出:(

4

1 回答 1

5

正如预期的那样,您的第一个外部连接会产生:

| 原因 | 月 |
------------------
| 一个 | 五月 |
| 一个 | 五月 |
| 一个 | 七月 |
| 一个 | 六月 |
| 乙| 五月 |
| 乙| 六月 |
| D | (空) |

但是,因为如果至少满足一次连接条件,外连接会产生结果(并且只有NULL在条件从未满足时才引入记录),所以您的第二个外连接不会产生 ; 的记录(B, July)。它也完全下降Reason = 'D',因为加入条件没有得到满足(并且所有三个月都在其他地方得到满足):

| 原因 | 月 |
------------------
| 一个 | 五月 |
| 一个 | 五月 |
| 乙| 五月 |
| 一个 | 六月 |
| 乙| 六月 |
| 一个 | 七月 |

虽然您可以Reason = 'D' 通过添加 加入条件来解决损失OR a.Month IS NULL,但您仍然不会产生(B, July). 相反,因为你想获得每一对(Reason, Month),你必须用CROSS JOIN你的物化Reasons表和你的物化Months表:

SELECT Reason, Month
FROM   
  (
    SELECT 'A' AS Reason
    UNION ALL SELECT 'B'
    UNION ALL SELECT 'D'
  ) Reasons CROSS JOIN (
    SELECT 'May' AS Month
    UNION ALL SELECT 'June'
    UNION ALL SELECT 'July'
  ) Months
| 原因 | 月 |
------------------
| 一个 | 五月 |
| 乙| 五月 |
| D | 五月 |
| 一个 | 六月 |
| 乙| 六月 |
| D | 六月 |
| 一个 | 七月 |
| 乙| 七月 |
| D | 七月 |

sqlfiddle上查看。

然后,您只需要将结果与您的基础数据进行外部连接:

SELECT Reason, Month, SUM(Down_time) downtime
FROM   
  (
    SELECT 'A' AS Reason
    UNION ALL SELECT 'B'
    UNION ALL SELECT 'D'
  ) Reasons CROSS JOIN (
    SELECT 'May' AS Month
    UNION ALL SELECT 'June'
    UNION ALL SELECT 'July'
  ) Months
  LEFT JOIN tabledown USING (Reason, Month)
GROUP BY Reason, Month
| 原因 | 月 | 停机时间 |
-----------------------------------------
| 一个 | 七月 | 3 |
| 一个 | 六月 | 8 |
| 一个 | 五月 | 7 |
| 乙| 七月 | (空) |
| 乙| 六月 | 6 |
| 乙| 五月 | 5 |
| D | 七月 | (空) |
| D | 六月 | (空) |
| D | 五月 | (空) |

sqlfiddle上查看。

于 2012-12-02T10:09:52.963 回答