GROUP BY的总和不显示零和

时间:2018-08-02 08:34:21

标签: sql sql-server case

我正在尝试从单个表中获取数据。我按CURR分组。我列出了12个条件。但是有些是零。

SELECT ISNULL(SUM(AMOUNT), 0) AS TOPL,
    CURR
FROM XXX 
WHERE DATEPART(year, CONVERT(dateTime, DATE)) = 2018 
    AND DATEPART(month, CONVERT(dateTime, DATE)) = 1
GROUP BY CURR

这将返回3值。但是我想要12个值,包括零和。我用CASE尝试过,但不能。

Figure I want to show

谢谢...

3 个答案:

答案 0 :(得分:2)

其他人试图告诉您的是,您需要“列表”您要在结果中看到的CURR值。通常,它们将来自规范化数据库中的另一个表。你是否有一个?似乎没有,但是值得一问。正确规范化的数据库通常会有一个。

那么您如何动态创建此列表?让我们假设您现有的表对于结果集中所需的每个CURR值至少有一行,即使该行的日期不在您感兴趣的日期之外。我们可以使用它来形成此列表,然后将该列表外部连接到进行求和的现有查询。

with curr_list as (select distinct CURR from dbo.XXX)
select curr_list.CURR, 
       sum(isnull(tbl.AMOUNT)) as TOPL 
from curr_list left join dbo.XXX as tbl 
   on curr_list.CURR = tbl.CURR 
   and tbl.[DATE] >= '20180101' 
   and tbl.[DATE] < '20180201'
group by curr_list.CURR
order by curr_list.CURR;

假设我没有打错字,那应该可以。 CTE(名为curr_list)创建要在结果集中看到的ID值的列表。当您将其外部连接到交易数据时,每个CURR值至少会获得一行。然后,您对每个CURR值求和以将这些行汇总为一行。请注意日期标准的更改。您的原始方法会阻止优化器在该列上使用任何有用的索引。

如果您现有的表没有在结果中想要的每个CURR值都没有一行,那么您只需更改cte并将所需的值硬编码即可。

答案 1 :(得分:0)

我可能会明白你的意思。

如果您有12 CURR(我在猜货币吗?),并希望按货币分组来获取2018年1月的交易总额。

如果是这种情况,这就是您应该尝试做的事情:

SELECT ISNULL(SUM(AMOUNT), 0) AS TOPL,
    CURR_TABLE.CURR
FROM CURR_TABLE 
LEFT JOIN XXX ON XXX.CURR = CURR_TABLE.CURR
WHERE DATEPART(year, CONVERT(dateTime, XXX.DATE)) = 2018 
    AND DATEPART(month, CONVERT(dateTime, XXX.DATE)) = 1
GROUP BY CURR_TABLE.CURR

这样,您将获得所有列出的货币(即使该月没有该货币的记录)。

编辑:

当您可以避免时,我不喜欢这种语法,但是您可以:

SELECT ISNULL(SUM(AMOUNT), 0) AS TOPL,
    CURR_TABLE.CURR
FROM (SELECT distinct CURR FROM XXX) CURR_TABLE
LEFT JOIN XXX ON XXX.CURR = CURR_TABLE.CURR
WHERE DATEPART(year, CONVERT(dateTime, XXX.DATE)) = 2018 
    AND DATEPART(month, CONVERT(dateTime, XXX.DATE)) = 1
GROUP BY CURR_TABLE.CURR

答案 2 :(得分:0)

请执行以下查询,并与您的预期输出进行比较。

SELECT CURR, SUM(ISNULL(AMOUNT,0)) AS TOPL,
    CURR
FROM XXX 
WHERE DATEPART(year, CONVERT(dateTime, DATE)) = 2018 
    AND DATEPART(month, CONVERT(dateTime, DATE)) = 1
GROUP BY CURR