First commit, 已上架的電子書
This commit is contained in:
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
根據 20241226-南港meeting
|
||||
BI 正航包 的資料結構
|
||||
|
||||
|
||||
《建立通用 DW 及 DashBoard》
|
||||
新建立下列 DW,這是通用的 DW,任何現有的 ERP 都可以透過 ETL 將資料寫入,然後就可以配合已經設計好的 DashBoard 顯示
|
||||
讓 BI 立刻無縫導入,提高客戶的使用意願
|
||||
|
||||
???
|
||||
alter table dw_product_sales_statistics add esti_sales_amount decimal(18,2)
|
||||
alter table dw_product_sales_statistics add esti_sales_qty decimal(10,2)
|
||||
alter table dw_product_sales_statistics add esti_sales_profit decimal(18,2)
|
||||
|
||||
Michael 20250530
|
||||
*/
|
||||
|
||||
-- 全公司統計
|
||||
create table dw_company_statistics (
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
number_of_quot int, -- 報價單數
|
||||
number_of_order int, -- 訂單數
|
||||
number_of_sales int, -- 出貨單數
|
||||
number_of_return int, -- 退貨單數
|
||||
sales_amount decimal(18,2), -- 總銷售金額
|
||||
sales_qty decimal(10,2), -- 總銷售數量
|
||||
item_cost decimal(18,2), -- 總銷售成本
|
||||
sales_profit decimal(18,2) -- 總銷售毛利
|
||||
primary key (stats_yymm)
|
||||
)
|
||||
|
||||
-- 產品銷售統計
|
||||
create table dw_product_sales_statistics (
|
||||
productid varchar(50) not null,
|
||||
productname nvarchar(100),
|
||||
productclassid varchar(10),
|
||||
productclassname nvarchar(100),
|
||||
-- new 新增品牌統計
|
||||
brand_id varchar(20),
|
||||
brand_name nvarchar(100),
|
||||
--
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
-- 新增預估欄位(Estimate) > 計算達成率
|
||||
-- esti_sales_amount decimal(18,2),
|
||||
-- esti_sales_qty decimal(10,2),
|
||||
-- esti_sales_profit decimal(18,2),
|
||||
primary key (productid,stats_yymm)
|
||||
)
|
||||
|
||||
insert into dw_product_sales_statistics ()
|
||||
select * from dw_tmp_sales_data
|
||||
|
||||
-- 產品類別銷售統計
|
||||
-- 基本上應該是由【產品銷售統計】再次計算得來
|
||||
create table dw_productclass_sales_statistics (
|
||||
productclassid varchar(10),
|
||||
productclassname nvarchar(100),
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
primary key (productclassid,stats_yymm)
|
||||
)
|
||||
|
||||
-- 品牌銷售統計(New)
|
||||
-- 基本上應該是由【產品銷售統計】再次計算得來
|
||||
create table dw_brand_sales_statistics (
|
||||
brand_id varchar(20),
|
||||
brand_name nvarchar(100),
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
primary key (brand_id,stats_yymm)
|
||||
)
|
||||
|
||||
-- 客戶銷售統計
|
||||
create table dw_customer_sales_statistics (
|
||||
custid varchar(50) not null,
|
||||
corpname nvarchar(100),
|
||||
custclassid varchar(10),
|
||||
custclassname nvarchar(100),
|
||||
/*
|
||||
areaid varchar(10),
|
||||
areaname nvarchar(100),
|
||||
channelid varchar(10),
|
||||
channelname nvarchar(100),
|
||||
*/
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
-- 應收帳款(每個月的一號計算前一個月的應收 TBD)
|
||||
ar decimal(18,2),
|
||||
primary key (custid,stats_yymm)
|
||||
)
|
||||
|
||||
-- 客戶類別銷售統計
|
||||
-- 基本上應該是由【客戶銷售統計】再次計算得來
|
||||
create table dw_customerclass_sales_statistics (
|
||||
custclassid varchar(10),
|
||||
custclassname nvarchar(100),
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
-- 應收帳款(每個月的一號計算前一個月的應收 TBD)
|
||||
ar decimal(18,2),
|
||||
primary key (custclassid,stats_yymm)
|
||||
)
|
||||
|
||||
-- 區域銷售統計
|
||||
-- 基本上應該是由【出貨單加總統計】計算得來
|
||||
create table dw_region_sales_statistics (
|
||||
regionid varchar(10),
|
||||
regionname nvarchar(100),
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
-- 應收帳款(每個月的一號計算前一個月的應收 TBD)
|
||||
ar decimal(18,2),
|
||||
primary key (regionid,stats_yymm)
|
||||
)
|
||||
|
||||
-- 通路銷售統計
|
||||
-- 基本上應該是由【出貨單加總統計】計算得來
|
||||
create table dw_channel_sales_statistics (
|
||||
channelid varchar(10),
|
||||
channelname nvarchar(100),
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
-- 應收帳款(每個月的一號計算前一個月的應收 TBD)
|
||||
ar decimal(18,2),
|
||||
primary key (channelid,stats_yymm)
|
||||
)
|
||||
|
||||
-- BU 銷售統計
|
||||
-- BU 企業內部的一個業務單位或分支,通常具有獨立的運營、產品線或市場責任
|
||||
create table dw_bu_sales_statistics (
|
||||
buid varchar(50) not null,
|
||||
buname nvarchar(100),
|
||||
stats_year varchar(4),
|
||||
stats_yymm varchar(6) not null,
|
||||
sales_amount decimal(18,2),
|
||||
sales_qty decimal(10,2),
|
||||
item_cost decimal(18,2),
|
||||
sales_profit decimal(18,2),
|
||||
primary key (buid,stats_yymm)
|
||||
)
|
||||
|
||||
|
||||
-- 一些基礎的暫存資料
|
||||
-- 加入品牌及分類(new) + hotel define(Jack) Id+Name
|
||||
create table dw_tmp_data (
|
||||
id_type varchar(10) not null,
|
||||
id_no varchar(50) not null,
|
||||
id_name nvarchar(100),
|
||||
id_desc nvarchar(100),
|
||||
sales_price decimal(18,2),
|
||||
sales_qty decimal(10,2)
|
||||
primary key (id_type,id_no)
|
||||
)
|
||||
|
||||
|
||||
-- 其他銷售統計
|
||||
-- 其他銷售統計
|
||||
|
||||
-- DE-BI DJI 部分參考資料
|
||||
create table dw_tmp_sales_data (
|
||||
銷售日期 varchar(10),
|
||||
進銷碼 varchar(20),
|
||||
進銷碼名稱 nvarchar(100),
|
||||
銷售人員 varchar(50),
|
||||
數量 int,
|
||||
合計金額 int,
|
||||
未稅金額 int,
|
||||
後台成本 int,
|
||||
後台毛利 int,
|
||||
建議售價 int,
|
||||
分店簡稱 nvarchar(20),
|
||||
分店代碼 varchar(10),
|
||||
大分類 nvarchar(100),
|
||||
中分類 nvarchar(100),
|
||||
小分類 nvarchar(100),
|
||||
督導區域 nvarchar(100),
|
||||
週報 nvarchar(100),
|
||||
商品品牌 nvarchar(100)
|
||||
)
|
||||
|
||||
|
||||
-- 將資料寫入dw_product_sales_statistics (TBD)
|
||||
with d0 as
|
||||
(
|
||||
select
|
||||
進銷碼 productid,進銷碼名稱 productname,分店簡稱,週報,商品品牌 as brand,商品品牌,substring(銷售日期,1,4) sdate,substring(銷售日期,1,6) mdate,合計金額,數量,後台成本,後台毛利
|
||||
from dw_tmp_sales_data
|
||||
), d1 as
|
||||
(
|
||||
select productid,productname,分店簡稱,週報,brand,商品品牌,sdate,mdate,sum(合計金額) AMT1,sum(數量) AMT2,sum(後台成本) AMT3,sum(後台毛利) AMT4
|
||||
from d0
|
||||
group by productid,productname,分店簡稱,週報,brand,商品品牌,sdate,mdate
|
||||
)
|
||||
insert into dw_product_sales_statistics (productid,productname,productclassid,productclassname,brand_id,brand_name,stats_year,stats_yymm,sales_amount,sales_qty,item_cost,sales_profit)
|
||||
select * from d1
|
||||
|
||||
|
||||
/*
|
||||
1.先純手工編出 202301 的資料(盡量合理) >> 推算出 2023 及 2024 兩年的全部 24 個月的資料
|
||||
月營業額 10,000,000
|
||||
月銷量 1200
|
||||
成本 sales_amount * 65%
|
||||
2.合理的分配到 product 及 customer 上(類別透過計算)
|
||||
一樣都先設定 202301 為基準的參考月份
|
||||
|
||||
|
||||
|
||||
202302 >>> * 1.55
|
||||
202303 >>> * 0.8
|
||||
202304 >>> * 0.7
|
||||
202305 >>> * 0.92
|
||||
202306 >>> * 1.15
|
||||
202307 >>> * 1.2
|
||||
202308 >>> * 1.38
|
||||
202309 >>> * 1.12
|
||||
202310 >>> * 0.92
|
||||
202311 >>> * 0.98
|
||||
202312 >>> * 1.05
|
||||
|
||||
202401 >>> * 1.2
|
||||
202402 >>> * 1.62
|
||||
202403 >>> * 0.92
|
||||
202404 >>> * 0.88
|
||||
202405 >>> * 0.96
|
||||
202406 >>> * 1.09
|
||||
202407 >>> * 1.19
|
||||
202408 >>> * 1.33
|
||||
202409 >>> * 1.52
|
||||
202410 >>> * 0.88
|
||||
202411 >>> * 0.91
|
||||
202412 >>> * 1.2
|
||||
*/
|
||||
|
||||
/*
|
||||
MI 小米
|
||||
RedMI 紅米
|
||||
select * from dw_product_sales_statistics where brand_id is null
|
||||
|
||||
update dw_product_sales_statistics set brand_id = 'RedMI',brand_name='紅米'
|
||||
where productname like '%紅米%';
|
||||
|
||||
update dw_product_sales_statistics set brand_id = 'MI',brand_name='小米'
|
||||
where productname like '%小米%' and brand_id is null
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
以下是和 Hotel 有關的 Table
|
||||
*/
|
||||
|
||||
-- 加入 Hotel 的 Demo 資料集
|
||||
-- 業績預估
|
||||
create table dw_hotel_esti_data (
|
||||
hotel_id varchar(10) not null, -- hotel id
|
||||
hotel_name nvarchar(100),
|
||||
stats_year varchar(4), -- 統計年
|
||||
stats_yymm varchar(6) not null, -- 統計年月
|
||||
esti_month_amount int, -- 月預估營業額
|
||||
primary key (hotel_id,stats_yymm)
|
||||
)
|
||||
|
||||
-- 實際業績
|
||||
/*
|
||||
住房率 = (order_no / hotel_room_no) * 100
|
||||
平均房價 sum(sales_week_amount) / hotel_room_no
|
||||
達成率 = (sum(sales_week_amount) / esti_month_amount) * 100
|
||||
|
||||
*/
|
||||
create table dw_hotel_data (
|
||||
hotel_id varchar(10) not null, -- hotel id
|
||||
hotel_name nvarchar(100),
|
||||
hotel_room_no int, -- 房間數
|
||||
stats_year varchar(4), -- 統計年
|
||||
stats_yymm varchar(6) not null, -- 統計年月
|
||||
week_number int, -- 年度週數
|
||||
WeekStart date,
|
||||
WeekEnd date,
|
||||
order_no int, -- 訂房數
|
||||
sales_week_amount int, -- 週營業額
|
||||
primary key (hotel_id,stats_yymm,week_number)
|
||||
)
|
||||
|
||||
-- 實際業績的年月統計(sum from )
|
||||
-- 本 Table 可以用 View=v_dw_hotel_sum_data 完全代替 (除非資料會很大,否則不建議使用)
|
||||
/*
|
||||
delete from dw_hotel_sum_data where stats_year = '2025';
|
||||
|
||||
insert into dw_hotel_sum_data (hotel_id,hotel_name,stats_year,stats_yymm,month_amount)
|
||||
select hotel_id,hotel_name,stats_year,stats_yymm,sum(sales_week_amount) from dw_hotel_data
|
||||
where stats_year = '2025'
|
||||
group by hotel_id,hotel_name,stats_year,stats_yymm;
|
||||
*/
|
||||
create table dw_hotel_sum_data (
|
||||
hotel_id varchar(10) not null, -- hotel id
|
||||
hotel_name nvarchar(100),
|
||||
stats_year varchar(4), -- 統計年
|
||||
stats_yymm varchar(6) not null, -- 統計年月
|
||||
month_amount int, -- 月預估營業額
|
||||
primary key (hotel_id,stats_yymm)
|
||||
)
|
||||
|
||||
|
||||
-- 產生 hotel 的基本資料, 部分欄位要候補
|
||||
with week_data as
|
||||
(
|
||||
select min(WeekNumber)-1 min_week,max(WeekNumber) max_week from Year_WeekData where MonthNumber = 5
|
||||
)
|
||||
-- insert into dw_hotel_data (hotel_id,hotel_name,hotel_room_no,stats_year,stats_yymm,week_number,WeekStart,WeekEnd,order_no,sales_week_amount)
|
||||
select
|
||||
T.id_no,T.id_name,0,'2025','202505',
|
||||
--WD.min_week,WD.max_week,
|
||||
YW.WeekNumber,YW.StartDate,YW.EndDate,0,0
|
||||
from dw_tmp_data T
|
||||
left join week_data WD on 1=1
|
||||
left join Year_WeekData YW on 1=1
|
||||
where T.id_type = 'hotel'
|
||||
and YW.WeekNumber >= WD.min_week and YW.WeekNumber <= WD.max_week
|
||||
order by 3,1
|
||||
|
||||
-- 2025 1-6 月(Now Data)
|
||||
-- insert into dw_hotel_data (hotel_id,hotel_name,hotel_room_no,stats_year,stats_yymm,week_number,WeekStart,WeekEnd,order_no,sales_week_amount)
|
||||
select
|
||||
T.id_no,T.id_name,T.sales_qty,'2025',convert(varchar(4),YW.StartDate,112)+case when YW.MonthNumber < 10 then '0'+cast(YW.MonthNumber as varchar) else cast(YW.MonthNumber as varchar) end,
|
||||
YW.WeekNumber,YW.StartDate,YW.EndDate,
|
||||
--FLOOR(RAND(CHECKSUM(NEWID())) * (75 - 35 + 1)) + 35,
|
||||
round(T.sales_qty*7*((FLOOR(RAND(CHECKSUM(NEWID())) * (65 - 35 + 1)) + 25)/100),0),
|
||||
round(T.sales_qty*7*((FLOOR(RAND(CHECKSUM(NEWID())) * (65 - 35 + 1)) + 25)/100)*1800,0)
|
||||
from dw_tmp_data T
|
||||
-- left join week_data WD on 1=1
|
||||
left join Year_WeekData YW on 1=1
|
||||
where T.id_type = 'hotel'
|
||||
and YW.WeekNumber <=40
|
||||
order by 1,6;
|
||||
|
||||
/*
|
||||
達成率
|
||||
配合 metabase 元件,只能有一個數字
|
||||
H01-H07 各飯店-當月達成率
|
||||
*/
|
||||
select
|
||||
--H.hotel_id,H.hotel_name,H.stats_yymm,
|
||||
--(H.month_amount*1.0/E.esti_month_amount*1.0)*100,
|
||||
(H.month_amount*1.0 / (case when E.esti_month_amount = 0 then 1 else E.esti_month_amount end)) * 100 as pass_rate
|
||||
from dw_hotel_sum_data H
|
||||
left join dw_hotel_esti_data E on H.hotel_id = E.hotel_id and H.stats_yymm = E.stats_yymm
|
||||
where hotel_id = 'H01' and H.stats_yymm = convert(char(6), getdate(), 112)
|
||||
|
||||
|
||||
select
|
||||
H.hotel_id,H.hotel_name,H.stats_yymm,H.month_amount,E.esti_month_amount,
|
||||
(H.month_amount*1.0 / (case when E.esti_month_amount = 0 then 1 else E.esti_month_amount end)) * 100 as pass_rate
|
||||
from dw_hotel_sum_data H
|
||||
left join dw_hotel_esti_data E on H.hotel_id = E.hotel_id and H.stats_yymm = E.stats_yymm
|
||||
where H.stats_year = convert(char(4), getdate(), 112)
|
||||
|
||||
|
||||
-- 可以用這個 View 代替實體的 Table=dw_hotel_sum_data
|
||||
CREATE VIEW v_dw_hotel_sum_data AS
|
||||
SELECT
|
||||
hotel_id,
|
||||
hotel_name,
|
||||
stats_year, -- 統計年
|
||||
stats_yymm, -- 統計年月
|
||||
sum(sales_week_amount) month_amount -- 月預估營業額
|
||||
FROM dw_hotel_data H
|
||||
group by hotel_id,hotel_name,stats_yymm
|
||||
|
||||
|
||||
-- 樞紐分析(配合 Metabase 使用)
|
||||
CREATE VIEW v_hotel_monthly_pass_rate AS
|
||||
with hotel_data as
|
||||
(
|
||||
SELECT
|
||||
hotel_id,
|
||||
hotel_name,
|
||||
stats_yymm,
|
||||
sum(sales_week_amount) month_amount
|
||||
FROM dw_hotel_data H
|
||||
group by hotel_id,hotel_name,stats_yymm
|
||||
)
|
||||
select
|
||||
H.hotel_id,
|
||||
H.hotel_name,
|
||||
H.stats_yymm,
|
||||
H.month_amount,
|
||||
E.esti_month_amount,
|
||||
(H.month_amount * 1.0 / NULLIF(E.esti_month_amount, 0)) * 100 AS pass_rate
|
||||
from hotel_data H
|
||||
LEFT JOIN dw_hotel_esti_data E
|
||||
ON H.hotel_id = E.hotel_id AND H.stats_yymm = E.stats_yymm;
|
||||
|
||||
|
||||
|
||||
|
||||
-- 樞紐分析(配合 Metabase 使用) > 舊版(已不使用)
|
||||
CREATE VIEW v_hotel_monthly_pass_rate AS
|
||||
SELECT
|
||||
H.hotel_id,
|
||||
H.hotel_name,
|
||||
H.stats_yymm,
|
||||
H.month_amount,
|
||||
E.esti_month_amount,
|
||||
(H.month_amount * 1.0 / NULLIF(E.esti_month_amount, 0)) * 100 AS pass_rate
|
||||
FROM dw_hotel_sum_data H
|
||||
LEFT JOIN dw_hotel_esti_data E
|
||||
ON H.hotel_id = E.hotel_id AND H.stats_yymm = E.stats_yymm
|
||||
Reference in New Issue
Block a user