使用左外连接进行数据聚合

时间:2015-01-13 15:47:29

标签: sql sql-server group-by outer-join

我试图通过分支,按周来提取一些具有事务计数的数据,这将在以后用于提供一些动态.Net图表。

我有一个日历表,我有一个分支表,我有一个交易表。

这是我的数据库信息(仅包括相关列):

分支表:

ID (int), Branch (varchar)

日历表:

Date (datetime), WeekOfYear(int)

交易表:

Date (datetime), Branch (int), TransactionCount(int)

所以,我想做类似以下的事情:

Select b.Branch, c.WeekOfYear, sum(TransactionCount)
FROM BranchTable b
LEFT OUTER JOIN TransactionTable t
    on t.Branch = b.ID
JOIN Calendar c
    on t.Date = c.Date
WHERE YEAR(c.Date) = @Year // (SP accepts this parameter)
GROUP BY b.Branch, c.WeekOfYear

现在,当分支在一周内没有任何交易时,这会运行 EXCEPT ,在这种情况下,该分支会返回 NO RECORD 。我想要的是获得那个分支,那个星期和“0”的总和。我尝试了isnull(sum(TransactionCount),0) - 但这也没有用。因此,我将得到以下内容(为了说明目的而弥补金额):

+--------+------------+-----+
| Branch | WeekOfYear | Sum |
+--------+------------+-----+
|      1 |          1 |  25 |
|      2 |          1 |  37 |
|      3 |          1 |  19 |
|      4 |          1 |   0 |  //THIS RECORD DOES NOT GET RETURNED, BUT I NEED IT!
|      1 |          2 |  64 |
|      2 |          2 |  34 |
|      3 |          2 |  53 |
|      4 |          2 |  11 |
+--------+------------+-----+

那么,为什么左外连接不起作用?不应该

任何帮助将不胜感激。谢谢!

编辑:样本表数据:

Branch表:

+----+---------------+
| ID |    Branch     |
+----+---------------+
|  1 | First Branch  |
|  2 | Second Branch |
|  3 | Third Branch  |
|  4 | Fourth Branch |
+----+---------------+

Calendar表:

+------------+------------+
|    Date    | WeekOfYear |
+------------+------------+
| 01/01/2015 |          1 |
| 01/02/2015 |          1 |
+------------+------------+

Transaction

+------------+--------+--------------+
|    Date    | Branch | Transactions |
+------------+--------+--------------+
| 01/01/2015 |      1 |           12 |
| 01/01/2015 |      1 |            9 |
| 01/01/2015 |      2 |            4 |
| 01/01/2015 |      2 |            2 |
| 01/01/2015 |      2 |           23 |
| 01/01/2015 |      3 |           42 |
| 01/01/2015 |      3 |           19 |
| 01/01/2015 |      3 |            7 |
+------------+--------+--------------+

2 个答案:

答案 0 :(得分:7)

如果要返回包含每个分支和每周的查询,那么您需要先创建一个完整的列表,然后使用LEFT JOIN来处理事务以获取计数。代码类似于:

select bc.Branch, 
   bc.WeekOfYear, 
   TotalTransaction = coalesce(sum(t.TransactionCount), 0)
from
(
  select b.id, b.branch, c.WeekOfYear, c.date
  from branch b
  cross join Calendar c
  -- if you want to limit the number of rows returned use a WHERE to limit the weeks
  -- so far in the year or using the date column
  WHERE c.date <= getdate()
   and YEAR(c.Date) = @Year // (SP accepts this parameter)
) bc
left join TransactionTable t
  on t.Date = bc.Date
  and bc.id = t.branch
GROUP BY bc.Branch, bc.WeekOfYear

See Demo

此代码将在子查询中创建每个日期的每个分支的完整列表。获得此列表后,您可以加入到交易中以获取总交易数,并且您可以根据需要返回每个日期。

答案 1 :(得分:2)

在引入交易之前带上日历

SELECT b.Branch, c.WeekOfYear, sum(TransactionCount)
FROM BranchTable b 
INNER JOIN CalendarTable c ON YEAR(c.Date) = @Year
LEFT JOIN TransactionTable t ON t.Branch = b.ID AND t.Date = c.Date
GROUP BY b.Branch, c.WeekOfYear
ORDER BY c.WeekOfYear, b.Branch