sql查询,用于按月份分组并显示记录的单个月份总和

8e2ybdfx  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(475)

我试着将带有特定描述的产品代码和这些年来一个月内销售的产品总数相加。

使用的两个表是:

CREATE TABLE product (
    prod_code          NUMBER(3) NOT NULL,
    prod_description   VARCHAR2(75) NOT NULL,
    prod_points        NUMBER(2) NOT NULL
);

CREATE TABLE product_sale (
    sale_no         NUMBER(8) NOT NULL,
    sale_datetime   DATE NOT NULL,
    sale_location   VARCHAR2(100) NOT NULL,
    prod_code       NUMBER(3) NOT NULL,
    officer_id     NUMBER(8) NOT NULL,
);

日期格式为“dd mon yyyy hh12:mi pm”。
到目前为止,我能够表述出:

select  
d.prod_description, 
extract(month from sale_datetime) as mon, 
count(d.prod_code) as count
from product d 
 join product_sale o on d.prod_code = o.prod_code
group by d.prod_description, extract(month from sale_datetime);
order by d.prod_code;

如何将计数分隔为不同的月份列,并在单独的列中获得计数的总和?

ctzwtxfj

ctzwtxfj1#

我只会使用条件聚合:

select d.prod_description, count(*) as total,
       sum(case when extract(month from sale_datetime) = 1 then 1 else 0 end) as jan, 
       sum(case when extract(month from sale_datetime) = 2 then 1 else 0 end) as feb, 
       . . .
from product d join
     product_sale o 
     on d.prod_code = o.prod_code
group by d.prod_code, d.prod_description
order by d.prod_code;

请注意,对于订购, prod_code 需要在 group by --或者需要使用聚合函数,例如 order by min(d.prod_code) .
如果需要单独的行作为总计,则使用 grouping sets :

group by grouping sets ( (d.prod_code, d.prod_description), () )
js81xvg6

js81xvg62#

所以一月一栏应该包含每年一月的计数。
我假设除了水平和,你还需要垂直和。
首先,您需要在不同的级别上进行聚合,然后 PIVOT 将不同行的数据放入同一行的不同列中。
为了在不同级别进行聚合,oracle提供了 GROUP BY 扩展,例如 CUBE :

select prod_code, prod_description,
  nvl(extract(month from sale_datetime),0) mon,
  count(*) cnt
from product join product_sale using(prod_code)
group by cube((prod_code, prod_description), extract(month from sale_datetime))

现在您可以旋转:

select * from (
  select prod_code, prod_description,
    nvl(extract(month from sale_datetime),0) mon,
    count(*) cnt
  from product join product_sale using(prod_code)
  group by cube((prod_code, prod_description), extract(month from sale_datetime))
)
pivot(max(cnt) for mon in(
  0 sum,1 jan,2 feb,3 mar,4 apr,5 may,6 jun,7 jul,8 aug,9 sep,10 oct,11 nov,12 dec
))
order by prod_description;

PROD_CODE   PROD_DESCRIPTION   SUM    JAN   FEB   MAR   APR   MAY   JUN   JUL   AUG   SEP   OCT   NOV   DEC 
        1   1                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        2   2                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        3   3                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        4   4                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        5   5                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        6   6                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        7   7                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        8   8                  516     61    57    62    60    62    30    31    31    30    31    30    31 
        9   9                  516     61    57    62    60    62    30    31    31    30    31    30    31 
                              4644    549   513   558   540   558   270   279   279   270   279   270   279

这是一个简化的解决方案,例如,我没有在底部标记垂直总和行。有关此技术的完整解决方案和说明,请参阅https://stewashton.wordpress.com/2016/07/18/spreadsheet-like-totals-and-subtotals/

相关问题