2011-06-14 68 views
3

下面是一个查询组以小时为单位的交易通过pricepoint:MySQL的左外连接的麻烦

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”,而不是像现在那样不在那里。

尝试使用左外部连接。该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”放在价格点旁边,在给定小时内没有交易。

您的建议将受到欢迎!谢谢。

+0

也许左连接上一个子查询,你选择所有不同pricepoints?否则,我会用价格点的维度表。 – 2011-06-14 12:34:35

+0

事实上,这正是我最终做的,受到了安德鲁答案的启发。 – emx 2011-06-15 06:34:36

回答

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 

我现在没有时间去试试这个,所以让我知道如果它不起作用,我会尽量调整。

+0

谢谢安德鲁,这真的启发了我,我能够使用你的例子使它工作。 – emx 2011-06-15 06:32:14

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) 
+0

工会?不确定这是否是最佳解决方案... – 2011-06-14 12:49:15