MySQL留下外连接麻烦

时间:2011-06-14 12:21:53

标签: mysql group-by left-join

以下是按小时点按价格分组交易的查询:

SELECT hour(Stamp) AS hour, PointID AS pricepoint, count(1) AS counter
FROM Transactions
GROUP BY 1,2;

示例输出:

+------+------------+---------+
| hour | pricepoint | counter |
+------+------------+---------+
|    0 |         19 |       5 |
|    0 |         20 |      14 |
|    1 |         19 |       3 |
|    1 |         20 |      12 |
|    2 |         19 |       2 |
|    2 |         20 |       8 |
|    3 |         19 |       2 |
|    3 |         20 |       4 |
|    4 |         19 |       1 |
|    4 |         20 |       1 |
|    5 |         19 |       4 |
|    5 |         20 |       1 |
|    6 |         20 |       2 |
|    8 |         19 |       1 |
|    8 |         20 |       4 |
|    9 |         19 |       2 |
|    9 |         20 |       5 |
|   10 |         19 |       6 |
|   10 |         20 |       1 |
|   11 |         19 |      10 |
|   11 |         20 |       2 |
|   12 |         19 |      10 |
|   12 |         20 |       3 |
|   13 |         19 |      10 |
|   13 |         20 |      10 |
|   14 |         19 |       8 |
|   14 |         20 |       3 |
|   15 |         19 |       6 |
|   15 |         20 |       8 |
|   16 |         19 |      11 |
|   16 |         20 |      10 |
|   17 |         19 |       7 |
|   17 |         20 |      17 |
|   18 |         19 |       7 |
|   18 |         20 |       9 |
|   19 |         19 |      10 |
|   19 |         20 |      12 |
|   20 |         19 |      17 |
|   20 |         20 |      11 |
|   21 |         19 |      12 |
|   21 |         20 |      29 |
|   22 |         19 |       6 |
|   22 |         20 |      21 |
|   23 |         19 |       9 |
|   23 |         20 |      23 |
+------+------------+---------+

正如您所看到的,有些小时没有交易(例如早上7点),有些小时只有单个价格点的交易(例如早上6点,只有价格点20但没有价格点19的交易)。

我想在没有交易的情况下显示设置为“0”的结果,而不是像现在这样只是不存在。

尝试使用LEFT OUTER JOIN。 inHour 表包含值0..23

SELECT H.hour, PointID AS Pricepoint, COALESCE(T.counter, 0) AS Count
FROM inHour H
LEFT OUTER JOIN
(
 SELECT hour(Stamp) AS Hour, PointID, count(1) AS counter
 FROM Transactions
 GROUP BY 1,2
 ) T
ON T.Hour = H.hour;

这会产生以下输出(为简洁而截断):

|    5 |         19 |     4 |
|    5 |         20 |     1 |
|    6 |         20 |     2 |
|    7 |       NULL |     0 |
|    8 |         19 |     1 |
|    8 |         20 |     4 |

我实际上想要的是:

|    5 |         19 |     4 |
|    5 |         20 |     1 |
|    6 |         19 |     0 |
|    6 |         20 |     2 |
|    7 |         19 |     0 |
|    7 |         20 |     0 |
|    8 |         19 |     1 |
|    8 |         20 |     4 |

在我想要的输出中,值“0”放在给定小时内没有交易的价格点旁边。

欢迎您的建议!感谢。

2 个答案:

答案 0 :(得分:3)

SELECT h.Hour, p.Pricepoint, COUNT(t.*) AS Count
FROM inHour h,
(SELECT DISTINCT PointId AS Pricepoint FROM Transactions) p
LEFT OUTER JOIN Transactions t
ON h.Hour = hour(t.Stamp) AND p.Pricepoint = t.PointID
GROUP BY h.Hour, p.Pricepoint
ORDER BY h.Hour, p.Pricepoint

我现在没时间尝试这个,所以如果它不起作用请告诉我,我会尝试调整。

答案 1 :(得分:0)

有人可能有比这更好的解决方案,但我会使用UNION来简化事情:

SELECT hour(Stamp) AS hour, PointID AS pricepoint, count(1) AS counter
FROM Transactions
GROUP BY 1,2

UNION

SELECT hour,0 AS pricepoint,0 AS counter FROM inHour WHERE hour NOT IN (SELECT hour(Stamp) FROM Transactions)