如何执行仅使用 SQL 索引月份的 for 循环

How to perform a for loop indexing the month with SQL only

我正在尝试按月查询销量,因此我尝试每个月制作 12 列。到目前为止,我写了 12 行,每个月一行,但我想用一个 for 循环来优化它,索引月份数 ('01','02','03',...,'12'),如果可能的话,只用 SQL(我的数据库是一个Oracle 12c)。这是我的代码的 MWE:

select
       a.client,
       round(sum(decode(to_char(a.data,'mm'), '01', a.sales)), 2) as jan,
       round(sum(decode(to_char(a.data,'mm'), '02', a.sales)), 2) as feb,
       round(sum(decode(to_char(a.data,'mm'), '03', a.sales)), 2) as mar,
       round(sum(decode(to_char(a.data,'mm'), '04', a.sales)), 2) as apr,
       round(sum(decode(to_char(a.data,'mm'), '05', a.sales)), 2) as may,
       round(sum(decode(to_char(a.data,'mm'), '06', a.sales)), 2) as jun,
       round(sum(decode(to_char(a.data,'mm'), '07', a.sales)), 2) as jul,
       round(sum(decode(to_char(a.data,'mm'), '08', a.sales)), 2) as aug,
       round(sum(decode(to_char(a.data,'mm'), '09', a.sales)), 2) as sep,
       round(sum(decode(to_char(a.data,'mm'), '10', a.sales)), 2) as oct,
       round(sum(decode(to_char(a.data,'mm'), '11', a.sales)), 2) as nov,
       round(sum(decode(to_char(a.data,'mm'), '12', a.sales)), 2) as dez
  from salesmov         a,
       clients          b
 where 1e1 = 1e1
   and a.codcli = b.codcli
 group by a.client
;

SQL 没有 FOR 循环。

您可以使用 PIVOT 语句将 SUM 聚合应用于所有被透视的列:

SELECT *
FROM   (
  SELECT client,
         EXTRACT(MONTH FROM "DATE") AS month,
         ROUND(sales, 2) As sales
  FROM   salesmov a
  WHERE  EXISTS(SELECT 1 FROM clients b WHERE a.codcli = b.codcli)
)
PIVOT (
  SUM(sales) FOR month IN (
    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
  )
)

其中,对于示例数据:

CREATE TABLE salesmov (client, "DATE", sales, codcli) AS
SELECT 1, ADD_MONTHS(DATE '2022-01-01', LEVEL - 1), 100 * LEVEL, 1
FROM   DUAL
CONNECT BY LEVEL <= 12 UNION ALL
SELECT 2, ADD_MONTHS(DATE '2022-01-01', LEVEL - 1), 25 * LEVEL, 1
FROM   DUAL
CONNECT BY LEVEL <= 12;

CREATE TABLE clients (codcli) AS
SELECT 1 FROM DUAL;

输出:

CLIENT JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
1 100 200 300 400 500 600 700 800 900 1000 1100 1200
2 25 50 75 100 125 150 175 200 225 250 275 300

db<>fiddle here