SQL 解鎖 - 模擬揀貨位置

DigNo Ape-avatar-img
發佈於SQL
更新於 發佈於 閱讀時間約 8 分鐘
假設公司有5個配送中心(DC),如下圖,但不是所有商品都存放在所有的配送中心,舉例來說某辦公椅僅能存放在DC3和DC4,因此邏輯上美國東岸的需求會由DC3所配送(距離較近),西岸的需求會由DC4所配送。請根據上述邏輯使用SQL來模擬這商品在各地的需求會如何被配送、從哪個配送中心配送 (提供大方向即可)?
raw-image

我們在此篇會使用Tableau的 Superstores 裡的Orders,並會用Microsoft SQL Server 的SQL語法來講解概念。

我們假設所有的訂單都可以從這五個的配送中心直接配送。這五個的配送中心 ZIP code分別是12553, 29172, 60563, 80023, 92551,我們同時列出了經緯度如下表(存於[dbo].DC_ZIP)。

raw-image


計算距離

要能模擬訂單需求如何配送,我們的第一步是算出這些配送中心每筆訂單和這些配送中心的距離,才能知道哪個配送中心是離終點位置最近且有備存貨。我們使用以下的程式碼先生成一個主表。

SELECT
distinct [Product ID]
, LEFT(A.[Product ID],6) PRODUCT_GROUP
, A.[Order ID] [ORDER_ID]
, A.[Postal Code] DEST_ZIP
, A.[Latitude] DEST_LAT
, A.[Longitude] DEST_LONG
, B.DC_NUMBER
, CAST(B.Zip5 AS INT) SOURCE_ZIP
, B.[Latitude] SOURCE_LAT
, B.[Longitude] SOURCE_LONG
INTO [dbo].[SOURCE_DEST_PRODUCT_COMBO]
FROM [dbo].[Orders] A ,[dbo].[DC_ZIP] B


// SQL小貼士
// 1​
SELECT *
INTO [新資料表]
FROM [現有資料表];

// 2
// 在FROM裡,如果沒使用JOIN,直接在兩張資料表中加一個",",意味​會回傳兩表所有的可能排列
// ,也可以使用CROSS JOIN產生笛卡兒乘積 (Cartesian product)。

// 3 LEFT(欄位或字串, 左側擷取字符數)


增加一個距離欄位。

Alter table [dbo].[SOURCE_DEST_PRODUCT_COMBO]
Add Distance float;


使用經緯度求出直線距離。

Update [dbo].[SOURCE_DEST_PRODUCT_COMBO]
SET Distance =
2*ASIN(SQRT(SIN((3.14*SOURCE_LAT/180.0-3.14*DEST_LAT/180.0)/2)*SIN((3.14*SOURCE_LAT/180.0-3.14*DEST_LAT/180.0)/2)
+COS(3.14*SOURCE_LAT/180.0)*COS(3.14*DEST_LAT/180.0)*SIN((3.14*SOURCE_LONG/180.0-3.14*DEST_LONG/180.0)/2)*SIN((3.14*SOURCE_LONG/180.0-3.14*DEST_LONG/180.0)/2)))*3959


讓我們拿一些數字來驗證一下,

  • DC1 ZIP 12553 到某訂單地址 ZIP 42420: 762 英里 vs Google顯示756 英里。
raw-image


  • DC1 ZIP 12553 到某訂單地址 ZIP 90063: 2446 英里 vs Google顯示2445.8英里。
raw-image


找最近的DC

我們先來假設所有產品在每個配送中心都有存放,那邏輯上就是以最近的配送中心(RANKING = 1) 來揀貨並配送給客戶。

ALTER TABLE [dbo].[Orders]
ADD
SOURCE_DC_NUMBER INT;

UPDATE A
SET SOURCE_DC_NUMBER = B.DC_NUMBER
FROM [dbo].[Orders] A
INNER JOIN
(
SELECT *
FROM
(
SELECT DISTINCT DEST_ZIP
, DC_NUMBER
, DISTANCE
, Row_Number () OVER (PARTITION BY DEST_ZIP ORDER BY DISTANCE ASC) RANKING
FROM [dbo].SOURCE_DEST_PRODUCT_COMBO
) A
WHERE RANKING = 1
) B
ON
A.[Postal Code] = B.DEST_ZIP;


// SQL小貼士

// ROW_NUMBER()
// ROW_NUMBER()回傳不重複的累加序號,必須搭配​ OVER ()告訴SQL要如何產生序號。
// 若​需要分組排序,需在OVER()內再搭配PARTITION BY,這樣SQL會在每組組內產生序號。
// 以上述例子,讓SQL​以目的地的郵遞區號分組,並在每組目的地ZIP code以距離(與配送中心的距離)進行排序。
// => PARTITION BY 目的地的郵遞區號 ORDER BY 與配送中心的距離 ASC
// RANKING = 1 意味回傳最近的配送中心。


為避免過於複雜的狀況,我們假設每個Product Group (產品ID前六碼) 有獨特的存放分布,舉例來說。OFF-AP僅能存放在配送中心1-3。


raw-image


以這樣的例子,我們要在上述的程式碼加一些條件,除了要找最近的配送中心,還要找裡面有存貨的配送中心。以上述的例子,原本離配送中心4和5最近的訂單會被配送中心3所配送,因此配送中心3對於OFF-AP類的產品備貨要考慮整個西岸的需求。

ALTER TABLE [dbo].[Orders]
ADD
PRODUCT_GROUP NVARCHAR(255)
, SOURCE_DC_NUMBER_2 INT;

UPDATE A
SET PRODUCT_GROUP = LEFT(A.[Product ID],6)
FROM [dbo].[Orders] A;

UPDATE A
SET SOURCE_DC_NUMBER_2 = B.DC_NUMBER
FROM [dbo].[Orders] A
INNER JOIN
(
SELECT *
FROM
(
SELECT DISTINCT PRODUCT_GROUP
, DEST_ZIP
, DC_NUMBER
, DISTANCE
, Row_Number () Over (PARTITION BY PRODUCT_GROUP, DEST_ZIP ORDER BY DISTANCE Asc) RANKING
FROM [dbo].SOURCE_DEST_PRODUCT_COMBO
WHERE STOCKED = 'STOCKED'
) A
WHERE RANKING = 1
) B
ON
A.PRODUCT_GROUP = B.PRODUCT_GROUP
AND
A.[Postal Code] = B.DEST_ZIP;


// SQL小貼士
// 由於加上了每組Product Group存放分布不同,在PARTITION BY後要以Product Group+目的地郵遞區號進行分組
// => PARTITION BY Product Group, 目的地的郵遞區號 ORDER BY 與配送中心的距離 ASC
// 而且沒有存放的組合被納入排序中​。=> WHERE STOCKED = 'STOCKED'
// RANKING = 1 意味回傳最近且有存放此Product Group的配送中心。


遵循著我們上述的思考脈絡,希望能對您思考這類問題有所助益,也謝謝您撥冗完食。這些內容是根據我過去在外商的經驗,非常歡迎業界先進留言與我交流,我也會不定期補充我的觀點,也歡迎Follow我的Threads,持續都會有這類問題討論和生產力提升的點子喔!

留言
avatar-img
留言分享你的想法!
avatar-img
DigNo Ape 數遊原人
54會員
138內容數
我們秉持著從原人進化的精神,不斷追求智慧的累積和工具的運用來提升生產力。我們相信,每一個成員都擁有無限的潛力,透過學習和實踐,不斷成長和進步。
DigNo Ape 數遊原人的其他內容
2025/02/12
請以口語、白話形式解析以下SQL程式碼並描繪你認為的原資料表([Database].[Schema].[Table] )結構樣貌。 SELECT A.[Business_Unit], A.[Order_Number] , SUM([Sales_Units]) as [Sales_Uni
Thumbnail
2025/02/12
請以口語、白話形式解析以下SQL程式碼並描繪你認為的原資料表([Database].[Schema].[Table] )結構樣貌。 SELECT A.[Business_Unit], A.[Order_Number] , SUM([Sales_Units]) as [Sales_Uni
Thumbnail
2024/11/13
ABC 分析 ABC分析(ABC Analysis)是一種基於80/20的分類原則,常用於庫存管理、供應鏈分析和資源分配中。它將產品或項目按其相對重要性分為A、B 和 C三個類別。其目的是協助企業專注於最重要的項目,以提高效率和降低成本。
Thumbnail
2024/11/13
ABC 分析 ABC分析(ABC Analysis)是一種基於80/20的分類原則,常用於庫存管理、供應鏈分析和資源分配中。它將產品或項目按其相對重要性分為A、B 和 C三個類別。其目的是協助企業專注於最重要的項目,以提高效率和降低成本。
Thumbnail
2024/08/27
購物籃分析(Basket Analysis)是一種常見的資料探勘技術,可以幫助企業了解哪些產品經常被消費者一起購買,從而優化產品組合和促銷策略。 表1是將公司每筆訂單內容轉換為訂單號-SKU的組合,請使用SQL來進行購物籃分析,找出最常被一起下訂的產品組合。
2024/08/27
購物籃分析(Basket Analysis)是一種常見的資料探勘技術,可以幫助企業了解哪些產品經常被消費者一起購買,從而優化產品組合和促銷策略。 表1是將公司每筆訂單內容轉換為訂單號-SKU的組合,請使用SQL來進行購物籃分析,找出最常被一起下訂的產品組合。
看更多
你可能也想看
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
※ 為什麼我們需要 Transaction? 當我們談到 Transaction(交易)時,指的是一組不可分割的 SQL 操作。這些操作結果只能成功或失敗,以確保資料庫的一致性和完整性。Transaction 是資料庫操作中的一個「邏輯單位」,包含多個操作步驟。如果其中任何一個步驟失敗,整個 Tr
Thumbnail
※ 為什麼我們需要 Transaction? 當我們談到 Transaction(交易)時,指的是一組不可分割的 SQL 操作。這些操作結果只能成功或失敗,以確保資料庫的一致性和完整性。Transaction 是資料庫操作中的一個「邏輯單位」,包含多個操作步驟。如果其中任何一個步驟失敗,整個 Tr
Thumbnail
※ 什麼是ORDER BY? 可以讓SELECT出來的結果,根據你想要的方式排序。簡單說,用於對查詢結果進行排序。 ※ 語法: SELECT select_list FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC]
Thumbnail
※ 什麼是ORDER BY? 可以讓SELECT出來的結果,根據你想要的方式排序。簡單說,用於對查詢結果進行排序。 ※ 語法: SELECT select_list FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC]
Thumbnail
在工作情境中手動執行SQL語法更新中文字時,有時會遇到中文字顯示問號(?)的情況。這篇文章將介紹如何解決手動執行SQL語法時造成中文顯示問號(?)的方法。
Thumbnail
在工作情境中手動執行SQL語法更新中文字時,有時會遇到中文字顯示問號(?)的情況。這篇文章將介紹如何解決手動執行SQL語法時造成中文顯示問號(?)的方法。
Thumbnail
題目敘述 題目會給我們兩張資料表,第一張是Sales,第二張是Product。 第一張是Sales表格,裡面分別有sale_id、 product_id、year、quantity、price等欄位。其中(sale_id、 product_id)做為複合主鍵Primary key Table:
Thumbnail
題目敘述 題目會給我們兩張資料表,第一張是Sales,第二張是Product。 第一張是Sales表格,裡面分別有sale_id、 product_id、year、quantity、price等欄位。其中(sale_id、 product_id)做為複合主鍵Primary key Table:
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News