从DB获取每月统计数据的优雅方式(没有动态SQL)?

时间:2018-03-07 15:45:22

标签: sql pivot crosstab

考虑每月获得订单数量。我目前有这个:

select
  (select count(*) from orders o where o.created_at >= '2017-01-01' and o.created_at < '2017-02-01') as "Jan",
  (select count(*) from orders o where o.created_at >= '2017-02-01' and o.created_at < '2017-03-01') as "Feb",
  (select count(*) from orders o where o.created_at >= '2017-03-01' and o.created_at < '2017-04-01') as "Mar",
  (select count(*) from orders o where o.created_at >= '2017-04-01' and o.created_at < '2017-05-01') as "Apr",
  (select count(*) from orders o where o.created_at >= '2017-05-01' and o.created_at < '2017-06-01') as "May",
  (select count(*) from orders o where o.created_at >= '2017-06-01' and o.created_at < '2017-07-01') as "Jun",
  (select count(*) from orders o where o.created_at >= '2017-07-01' and o.created_at < '2017-08-01') as "Jul",
  (select count(*) from orders o where o.created_at >= '2017-08-01' and o.created_at < '2017-09-01') as "Aug",
  (select count(*) from orders o where o.created_at >= '2017-09-01' and o.created_at < '2017-10-01') as "Sep",
  (select count(*) from orders o where o.created_at >= '2017-10-01' and o.created_at < '2017-11-01') as "Oct",
  (select count(*) from orders o where o.created_at >= '2017-11-01' and o.created_at < '2017-12-01') as "Nov",
  (select count(*) from orders o where o.created_at >= '2017-12-01' and o.created_at < '2018-01-01') as "Dec"

是否有一种更加动态/可扩展的方式来实现这一目标而不需要使用动态SQL?

编辑:

  1. 我会接受SQL Server或Postgres的答案。我经常在这两个问题上运行这样的查询。
  2. 最小输出应与给定的查询匹配。但垂直输出会更好。

1 个答案:

答案 0 :(得分:0)

您没有指定DBMS,但如果您使用的是SQL Server,则可以执行以下操作:

SELECT [1] as Jan,[2] as Feb,[3] as Mar,[4] as Apr,[5] as May,[6] as Jun,
[7] as Jul,[8] as Aug,[9] as Sep,[10] as Oct,[11] as Nov,[12] as Dec
FROM (
         SELECT MONTH(o.created_at) as pivotmonth
         FROM orders o
         WHERE YEAR(o.created_at) = 2017
) xt
PIVOT (
    COUNT(xt.pivotmonth) FOR xt.pivotmonth IN (
    [1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) as pivottable

这样每月可以获得1列。