First commit, 已上架的電子書

This commit is contained in:
DATAEXPRESS\4734
2026-01-19 17:39:31 +08:00
commit 0b2351e4da
1146 changed files with 1442668 additions and 0 deletions
@@ -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