带有join,sum,group by等的SQL查询

时间:2009-03-28 15:10:02

标签: sql sql-server

我正在尝试构建一个如下所示的报告:

      jan feb mar apr may jun jul ago sep oct nov dec
food   0   1   1   2   0   0   3   1   0   0   1   1
car    1   0   0   0   1   2   1   0   1   2   3   4
home   0   0   1   2   2   2   5   1   2   4   0   0
other  0   0   0   0   0   0   0   0   0   0   0   0

我有两个表:t_itemt_valuet_item有两列:itemIDitemNamet_value有3列:itemIDvaluedate

使用以下查询,我可以生成包含所有itens的列表,即使是空列表也是如此。

SELECT t_item.itemID, ISNULL(SUM(t_value.value), 0) AS value
FROM t_value RIGHT OUTER JOIN t_item ON t_value.itemID = t_item.itemID
GROUP BY t_item.itemID

但是,如果我尝试包含MONTH列(如下所示),结果将仅显示具有值的项目......

SELECT t_item.itemID, ISNULL(SUM(t_value.value), 0) AS value, MONTH(date) AS date
FROM t_value RIGHT OUTER JOIN t_item ON t_value.itemID = t_item.itemID
GROUP BY t_item.itemID, MONTH(date)

有可能吗?如何在结果中包含没有值和组的itens,然后按月包含?

TIA,

鲍勃

4 个答案:

答案 0 :(得分:1)

对于数据中的“漏洞”,您需要一个填充表。使用完整的外部联接将该表连接到月份的事实表。

month
------
month --values jan through dec

对于格式化,您有几种选择。

  • 在报告工具中,使用交叉表或矩阵函数。
  • 在SQL中使用CASE函数。
  • 在SQL中使用Pivot函数。

答案 1 :(得分:1)

您是否正在使用具有交叉布功能的报告工具?

如果没有,您可以为每个月创建一个总和列。所以你的结果集实际上看起来就像那个报告样本。

SELECT t_item.itemID, 

--ISNULL(SUM(t_value.value), 0) AS value, 

sum(case when MONTH(date) = 1 then t_value.value else 0 end) AS m1_sum,
sum(case when MONTH(date) = 2 then t_value.value else 0 end) AS m2_sum,
sum(case when MONTH(date) = 3 then t_value.value else 0 end) AS m3_sum,
--etc

FROM t_value RIGHT OUTER JOIN t_item ON t_value.itemID = t_item.itemID
GROUP BY t_item.itemID

答案 2 :(得分:1)

以下是一个例子:

create table #months (value int, name varchar(12))
create table #items (value int, name varchar(24))
create table #sales (month int, item int, sales int)

insert into #months values (1, 'jan')
insert into #months values (2, 'feb')
insert into #months values (3, 'mar')

insert into #items values (1, 'apple')
insert into #items values (2, 'pear')
insert into #items values (3, 'nut')

insert into #sales values (1,1,12)
insert into #sales values (2,2,3)
insert into #sales values (2,2,5)
insert into #sales values (3,3,7)

您可以使用PIVOT表查询它,例如:

select *
from (
    select
        item = #items.name
    ,   month = #months.name
    ,   sales = isnull(sum(#sales.sales),0)
    from #months
    cross join #items
    left join #sales on #months.value = #sales.month 
         and #items.value = #sales.item
    group by #months.name, #items.name
) vw
pivot (sum(sales) for month in ([jan],[feb],[mar])) as PivotTable

或者作为替代方案,常规查询:

select
    item = #items.name
,   jan = sum(case when #sales.month = 1 then sales else 0 end)
,   feb = sum(case when #sales.month = 2 then sales else 0 end)
,   mar = sum(case when #sales.month = 3 then sales else 0 end)
from #items
left join #sales on #items.value = #sales.item
group by #items.name

两者都导致:

item        jan     feb     mar
apple       12      0       0
nut         0       0       7
pear        0       8       0

在第一个示例中,“交叉连接”确保所有月份和值都存在。然后它们“左连接”,因此即使没有值的行也会显示。

IsNull()就是在一个月没有出售该特定项目时显示0而不是NULL。

答案 3 :(得分:1)

WITH    calendar(mon) AS
        (
        SELECT  1
        UNION ALL
        SELECT  mon + 1
        FROM    calendar
        WHERE   mon < 12
        )
SELECT  itemID, mon, SUM(value)
FROM    calendar c, t_item i
LEFT OUTER JOIN
        t_value v
ON      v.itemID = i.itemID
        AND MONTH(date) = mon
GROUP BY
        i.itemID, mon