【mysql】创建视图查询当月累计销售额的案例
【mysql】创建视图查询当月累计销售额的案例
- 【一】案例描述
- 【二】需求描述
- 【三】解决方案
- 【四】实际案例
【一】案例描述
Doris中有如下几张表
(1)销售记录表
(2)日历维表表
(3)店铺维度表
(4)产品维度表
销售记录表会记录每天的销售记录,包括日期、店铺、产品、销售额,周末和节假日没有销售记录;日历维表表维护的是全量的日历;店铺表维护的是全量的店铺信息;产品表维护的是全量的产品表。
【二】需求描述
创建视图,从销售记录表中查询的是每天每个分公司每个产品的截止当天的各个维度的月度销售额,没有销售记录的维度默认补上一条销售额为0的记录
例如:
2025年7月,一共31天,7月1至7月4都是工作日,每天都有n条各个店铺的各个产品销售额(个别店铺装修或者产品下架会存在没有记录的情况),但是7月5是周末,没有销售记录。现在要统计的是当月销售额,如何实现sql
【三】解决方案
视图创建语句
CREATE VIEW sales_summary_optimized AS
WITH
-- 1. 获取当前日期及当月范围(动态限定月份)
current_info AS (SELECT CURRENT_DATE() AS today,DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01') AS month_start, -- 当月第一天CURRENT_DATE() AS month_end -- 截止当天(动态)
),
-- 2. 筛选当月有销售记录的活跃店铺和产品(分公司通过店铺关联)
active_shop_product AS (SELECT DISTINCT s.branch_id, -- 分公司ID(通过店铺表关联)sl.shop_id,sl.product_idFROM sales slJOIN shop s ON sl.shop_id = s.shop_idJOIN current_info ci ON sl.sale_date BETWEEN ci.month_start AND ci.month_end -- 仅当月有销售的记录
),
-- 3. 生成当月完整日期序列(含周末/节假日)
month_dates AS (SELECT c.date AS sale_dateFROM calendar cJOIN current_info ci ON c.date BETWEEN ci.month_start AND ci.month_end -- 仅当月日期
),
-- 4. 关联活跃维度与完整日期,计算每日销售额(无销售补0)
daily_sales AS (SELECT md.sale_date,asp.branch_id,asp.product_id,COALESCE(SUM(sl.amount), 0) AS daily_salesFROM month_dates mdCROSS JOIN active_shop_product asp -- 仅交叉当月活跃的分公司和产品LEFT JOIN sales sl ON md.sale_date = sl.sale_dateAND asp.shop_id = sl.shop_idAND asp.product_id = sl.product_idGROUP BY md.sale_date, asp.branch_id, asp.product_id
)
-- 5. 计算截止当天的月度累计销售额
SELECT sale_date,branch_id,product_id,daily_sales,SUM(daily_sales) OVER (PARTITION BY branch_id, product_id ORDER BY sale_dateROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS monthly_cumulative_sales
FROM daily_sales
ORDER BY sale_date, branch_id, product_id;
此视图适用于“关注当月活跃业务”的场景,例如:
• 当月有销售的分公司/产品才会出现在结果中(无销售的维度不显示)。
• 需实时反映“截止当天”的月度累计情况(随日期推进自动更新活跃维度)。
注意事项
• 如果需要包含“当月有维度但全月无销售”的记录(如新增分公司/产品),需额外关联全量维度表并左连接active_shop_product(按需调整)。
• 若数据量较大,建议将视图改为物化视图,并配置按日增量刷新(Doris支持物化视图定时刷新),提升查询效率。
【四】实际案例
with date_series as (
select'2024-01-01' as dt
union all
select'2024-01-02' as dt
union all
select'2024-01-03' as dt
union all
select'2024-01-04' as dt
union all
select'2024-01-05' as dt
union all
select'2024-01-06' as dt
union all
select'2024-01-07' as dt
union all
select'2024-01-08' as dt
union all
select'2024-01-09' as dt
union all
select'2024-01-10' as dt
union all
select'2024-01-11' as dt
union all
select'2024-01-12' as dt
union all
select'2024-01-13' as dt
union all
select'2024-01-14' as dt
union all
select'2024-01-15' as dt
union all
select'2024-01-16' as dt
union all
select'2024-01-17' as dt
union all
select'2024-01-18' as dt
union all
select'2024-01-19' as dt
union all
select'2024-01-20' as dt
union all
select'2024-01-21' as dt
union all
select'2024-01-22' as dtunion all
select'2024-01-23' as dt
union all
select'2024-01-24' as dt
union all
select'2024-01-25' as dt
union all
select'2024-01-26' as dt
union all
select'2024-01-27' as dt
union all
select'2024-01-28' as dt
union all
select'2024-01-29' as dtunion all
select'2024-01-30' as dt
union all
select'2024-01-31' as dt
),
origin_data as (-- 原子视图数据作为原始数据selectORG_ID,INDEX_CODE,INDEX_VERSION,STANDARD_BUSINESS_DATE,sum(INDEX_VALUE) as `INDEX_VALUE`,-- 月初日期作为开始日期,当前日期作为结束日期,DATE_FORMAT(`STANDARD_BUSINESS_DATE`, '%Y-%m-01') as `period_start_date`,STANDARD_BUSINESS_DATE as `period_end_date`fromdev_damp_ind.MID_VIEW_sadasdasdsadsawhere1 = 1group byORG_ID,INDEX_CODE,INDEX_VERSION,STANDARD_BUSINESS_DATE
),
distinct_dim_org as (-- 获取当月截止当天产生记录的全量机构维度select distinct ORG_ID from origin_data where STANDARD_BUSINESS_DATE between period_start_date and period_end_date
),
cross_dim as (
-- 将各个维度进行cross join得到笛卡尔积,补全缺失维度的数据记录select ds.dt as STANDARD_BUSINESS_DATE,ddo.ORG_ID as ORG_ID from date_series ds cross join distinct_dim_org ddo
),
cross_data as (
-- 将维度的笛卡尔积和记录表里的数据leftjoin,补充空值数据,得到全维度的记录信息select cd.STANDARD_BUSINESS_DATE,cd.ORG_ID,'ssyzzb_070401_online' as INDEX_CODE,'V2025072501' as INDEX_VERSION,coalesce(od.INDEX_VALUE,0) as INDEX_VALUE,coalesce(od.period_start_date,DATE_FORMAT(cd.STANDARD_BUSINESS_DATE, '%Y-%m-01')) as period_start_date,coalesce(od.period_start_date,cd.STANDARD_BUSINESS_DATE) as period_end_date from cross_dim cd left join origin_data od on cd.ORG_ID=od.ORG_ID and cd.STANDARD_BUSINESS_DATE=od.STANDARD_BUSINESS_DATE
),
cycle_data as (
-- 对每天的记录信息进行当月的sum聚合selectt.ORG_ID,t.INDEX_CODE,t.INDEX_VERSION,t.STANDARD_BUSINESS_DATE,od.`period_start_date`,od.`period_end_date`,sum(t2.INDEX_VALUE) as `INDEX_VALUE`fromcross_data tjoin cross_data od ont.ORG_ID = od.ORG_IDand t.INDEX_CODE = od.INDEX_CODEand t.INDEX_VERSION = od.INDEX_VERSIONand t.STANDARD_BUSINESS_DATE = od.STANDARD_BUSINESS_DATEjoin cross_data t2 ont.ORG_ID = t2.ORG_IDand t.INDEX_CODE = t2.INDEX_CODEand t.INDEX_VERSION = t2.INDEX_VERSIONand t2.`STANDARD_BUSINESS_DATE` between od.`period_start_date` and t.`period_end_date`group byt.ORG_ID,t.INDEX_CODE,t.INDEX_VERSION,t.STANDARD_BUSINESS_DATE,od.`period_start_date`,od.`period_end_date` order by STANDARD_BUSINESS_DATE asc
)
select * from cycle_data where STANDARD_BUSINESS_DATE='2024-01-22'
至此,即使原表中2024-01-22那一天没有任何记录,也能查出来2024-01-22那天当月的各个维度总值