【问题标题】:How do I get a 0 sum when grouping by more than one field?按多个字段分组时如何获得 0 总和?
【发布时间】:2016-04-18 17:30:35
【问题描述】:

我尝试查找并发现使用左外连接往往是答案,但这通常是日期分组的总和,而不是 2 级分组。我认为额外的分组让我很困惑。

我的桌子:

dbo._Labour

_id int pk --该劳动力条目的id
_date date -- 该条目的日期(使用它按年份分组)
_activityid int -- 他们正在做什么类型的活动
_typeid int --3 个可能的选项 (0,1,2) 他们正在执行活动的项目类型
_hours numeric(4,0) -- 执行该活动花费了多少小时。

我的最终目标是了解每年为 3 种类型 (0,1,2) 中的每一种工作所花费的总小时数。我当前的代码:

select coalesce(SUM(_hours),0) as _hours, YEAR(_date) as _year, l._typeid 
from RelayTanks.dbo._Labour l 
left outer join (select YEAR(_date) as _y 
from RelayTanks.dbo._Labour group by YEAR(_date)) y on y._y = YEAR(l._date) 
where _activityid in (3,4,9,11) 
group by YEAR(_date), l._typeid 
order by year(_date), l._typeid'

导致:

_typeid _year   _hours
0   2015    1174
1   2015    3953
2   2015    851
0   2016    119
1   2016    541
2   2016    65
1   2017    10

我正在寻找的是 2017 年显示 _typeid 0 的 _hours 0 和 _typeid 2 的 0。即:

_typeid _year   _hours
0   2015    1174
1   2015    3953
2   2015    851
0   2016    119
1   2016    541
2   2016    65
0   2017    0    
1   2017    10
2   2017    0

我已经尝试了很多东西,包括 2 个外部左连接,但我无法完全弄清楚。我认为当前的 out join 可以很好地替代实际拥有一个虚拟年表,并且只显示至少完成了一些工作的年份。

这是我在这里发布的第一个问题,如果我忽略了一些信息或遗漏了一些社区礼仪,我深表歉意。

感谢您的帮助!

【问题讨论】:

  • 将您的 typeid 列表与年份列表交叉加入,然后左加入该结果

标签: sql sql-server sql-server-2008-r2


【解决方案1】:

假设所有可能的年份和类型都已在您的数据中表示,这将使您到达那里:

SELECT year(_date), _typeid, _hours = SUM(_hours)
FROM _Labour
GROUP BY year(_date), _typeid
UNION
SELECT year(y._date), t._typeid, 0
FROM _Labour y, _Labour t
WHERE NOT EXISTS (SELECT 1 FROM _Labour WHERE year(_Labour._date) = year(y._date) AND _Labour._typeid = t._typeid)
ORDER BY 1, 2

【讨论】:

    【解决方案2】:

    如果你必须只用一张桌子来做这件事,那么这样的事情可能会奏效。

    SELECT  s._typeid,
            s._y,
            coalesce(SUM(lj._hours),0) as _hours
    FROM
    (   
        SELECT t._typeid, y._y
        FROM    (SELECT DISTINCT _typeid FROM RelayTanks.dbo._Labour) t
                CROSS JOIN 
                (SELECT DISTINCT YEAR(_date) _y FROM RelayTanks.dbo._Labour) y
    ) s
    LEFT JOIN RelayTanks.dbo._Labour lj ON lj._typeid = s._typeid AND YEAR(lj._date) = s._y
    

    性能可能很糟糕......您可能需要考虑为 _date.year 值添加一个计算列

    【讨论】:

    • 谢谢,这两个答案都有效。您的回答似乎很全面,我选择了@Bob-S,因为它对我来说更容易理解。两者对我来说都是很好的学习机会,我感谢你。
    • @enfrost 没问题.. 不是老式笛卡尔连接的忠实粉丝,但如果你能做到这一点,那就更棒了.. sqlfiddle.com/#!3/10b3d/1\
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    相关资源
    最近更新 更多