如何旋转和合并以避免 NULL 单元格?

How to pivot and merge to avoid the NULL cells?

示例 table 数据:

SELECT [id],[date],[agent],[sales]
  FROM [AgentSales]

id  date                    agent   sales
1   2021-01-02 00:00:00.000 Agent A 10
2   2021-01-03 00:00:00.000 Agent A 2
3   2021-01-04 00:00:00.000 Agent B 22
4   2021-01-06 00:00:00.000 Agent B 5
5   2021-02-05 00:00:00.000 Agent A 1
6   2021-02-06 00:00:00.000 Agent B 33
7   2021-03-06 00:00:00.000 Agent A 11
8   2021-03-06 00:00:00.000 Agent B 3

按年月分组,代理商:

SELECT CAST(YEAR([DATE]) AS VARCHAR)+' '+CAST(MONTH([DATE]) AS VARCHAR) YRMON, AGENT, SUM(SALES) SALES
  FROM AgentSales
  GROUP BY  CAST(YEAR([DATE]) AS VARCHAR)+' '+CAST(MONTH([DATE]) AS VARCHAR), AGENT
  ORDER BY 1

YRMON   AGENT   SALES
2021 1  Agent A 12
2021 1  Agent B 27
2021 2  Agent A 1
2021 2  Agent B 33
2021 3  Agent A 11
2021 3  Agent B 3

枢轴:

  SELECT CAST(YEAR([DATE]) AS VARCHAR)+' '+CAST(MONTH([DATE]) AS VARCHAR) YRMON, [AGENT A], [AGENT B]
  FROM AgentSales
  PIVOT (SUM(SALES) FOR AGENT IN ([AGENT A], [AGENT B])) AS PIVOTTABLE

YRMON   AGENT A AGENT B
2021 1  10      NULL
2021 1  2       NULL
2021 1  NULL    22
2021 1  NULL    5
2021 2  1       NULL
2021 2  NULL    33
2021 3  11      NULL
2021 3  NULL    3

我想用实际值代替 NULL。因此实际上每个 YearMon 应该只有 2 行。如何做到这一点?

预期结果:

  YRMON   AGENT A AGENT B
  2021 1  12      27
  2021 2  1       33
  2021 3  11      3

看起来简单的条件聚合应该可以解决问题。

SELECT
  FORMAT(EOMONTH([DATE]), 'yyyy MM') YRMON,
  SUM(CASE WHEN AGENT = 'AGENT B' THEN SALES END) [AGENT B],
  SUM(CASE WHEN AGENT = 'AGENT A' THEN SALES END) [AGENT A]
FROM AgentSales
GROUP BY EOMONTH([DATE])
ORDER BY EOMONTH([DATE]);

或者,如果您希望每一个都在单独的一行中,您可以添加一个行号并在其上分组

SELECT
  FORMAT(EOMONTH([DATE]), 'yyyy MM') YRMON,
  SUM(CASE WHEN AGENT = 'AGENT B' THEN SALES END) [AGENT B],
  SUM(CASE WHEN AGENT = 'AGENT A' THEN SALES END) [AGENT A]
FROM (
    SELECT *,
      rn = ROW_NUMBER() OVER (PARTITION BY EOMONTH([DATE]), AGENT ORDER BY [DATE])
    FROM AgentSales
) sales
GROUP BY EOMONTH([DATE]), rn
ORDER BY EOMONTH([DATE]), rn;

Grouping by EOMONTH is more performant than grouping by a string

db<>fiddle