2012-06-11 31 views
0

我正在嘗試將事務數據清理並滿足我的分析需求。如何將事務記錄到數據庫中有一些限制,並且我試圖解決這些限制。For SQL在SQL Server中 - 這是正確的邏輯?

當客戶下訂單超過1個產品時,交易數據庫不會將多個產品鏈接在一起。每個產品都有唯一的銷售ID,但無法將多個銷售ID分組爲一個訂單。以下是一個示例:

OrderID MultOrderID CustomerID SalesDate SalesTime ProductID ProductCost ShippingCost 
6082346     7661X0A  2012-06-12 959   105   99.99  7.95 
6082347 5809812YY6Y T891002  2012-06-12 1005  222   99.95  7.95 
6082348 5809812YY6Z T891002  2012-06-12 1005  273   22.95  1.00 
6082349 5809812YY71 T891002  2012-06-12 1005  285   499.95  1.00 
6082350 5809812YY72 T891002  2012-06-12 1005  172   49.95  1.00 
6082351 5809812YY73 T891002  2012-06-12 1005  105   99.99  7.95 
6082352 5809812YY74 X637251  2012-06-12 1010  285   499.95  7.95 
6082353 5809812YY75 X637251  2012-06-12 1010  30   1024.99  1.00 
6082354     T512AT0  2012-06-12 1017  172   49.95  7.95 

此交易系統的其他限制是它不能將多於4個的產品一起裝運。如果客戶訂購了5種產品,4種產品一起發貨(並收取1運費),剩餘的產品單獨發貨並收取另一運費(是的,整個企業希望重建這整個遺留系統... )。

我試圖確定的是每件訂單的產品數量以及總產品成本和運輸成本。

如果您查看MultOrderID的最後4個字符,您會看到它是順序的,YY6Y變成YY6Z,然後轉到YY71,YY72。邏輯是標準化的 - 我知道如果CustomerID,SalesDate和SalesTime是相同的,那麼我可以將產品配對在一起。我不知道的是如何才能做到這一點。

我相信實現這個目標的方法是通過CustomerID,SalesDate和SalesTime分解訂單。然後,我得到一個for-loop,或類似的東西來循環通過各個條目。然後,我查找MultOrderID的最後4個字符,並說 - 如果1,2和3是相同的,並且第4個字符在前一個順序的第4個字符之後,則將它們組合在一起,最多4個順序。如果訂單ID是範圍內的第5到第8個訂單,那麼這是裝運2等。

這可以在SQL Server完成嗎?如果不是這樣,我應該寫什麼?這是我應該在這種情況下使用的for-loop

編輯:這是我想要得到的輸出。請記住,在第四個產品發貨後,我需要重新開始訂購(所以,有6個產品分成2個發貨[4個產品和2個產品],9個產品分成3個發貨[4,4和1]

PRODUCTSSHIPPED SALESDATE SALESTIME CUSTOMERID PRODUCTCOST SHIPPINGCOST 
4    6/12/12   1005 T891002  672.8  10.95 
1    6/12/12   1005 T891002  99.99  7.95 
2    6/12/12   1010 X637251  1524.94  8.95 
1    6/12/12   1017 T512AT0  49.95  7.95 
1    6/12/12   959  7661X0A  99.99  7.95 
+0

感謝迄今爲止的答案 - 我認爲我需要的原因循環是我需要在4產品後創建新的貨物。我猜'CASE'會有足夠的邏輯,但稍後會嘗試。 – mikebmassey

+0

不確定是否通知您更新答案時,但我已更新我的 - 應該是您需要的 – Charleh

回答

2

那麼從這句話好像你想要這個:

我試圖確定的是每 爲了出貨產品的數量,總產品成本和運輸成本。

http://sqlfiddle.com/#!3/e0e71/30

所以我不知道你使用foreach循環是什麼意思?

UPDATE:

得到它的工作使用子查詢和天花板功能

更新了小提琴

FYI SQL是:

SELECT 
SalesDate, 
SalesTime, 
CustomerID, 
SUM(ProductCost), 
SUM(ShippingCost) 
FROM 

(
SELECT 
     SalesDate, 
     SalesTime, 
     CustomerID, 
     ProductCost, 
     ShippingCost, 
     ROW_NUMBER() OVER (PARTITION BY salesdate, salestime, customerid ORDER BY CustomerID) as ProdNumber 
FROM Orders 
) as Summary 
group by SalesDate, SalesTime, CustomerID, ceiling(ProdNumber/4.0) 

我用ROW_NUMBER得到的運行計數產品爲每個訂單,然後使這個子查詢,所以我可以做分組。該分組只使用了產品數量除以4(作爲浮點數),並使用上限函數將四捨五入到最接近的整數以將其分組到4

+0

再次閱讀它也看起來像你想獲得貨件號碼。這也是使用ROW_NUMBER微不足道 - 我會編輯小提琴 – Charleh

+0

當我回到家時,妻子期待着我回來,她會閹割我:D – Charleh

+0

謝謝 - 這是我最初遵循的邏輯,但它由於每批貨物4件產品的限制以及MultiOrderID翻到更高的第三個字符的事實。我將根據我在尋找輸出的內容編輯問題。 – mikebmassey

0

我不知道爲什麼需要在所有的循環..

Select count(*) as ProductsOnOrder, LEFT(CustomerID,4), as CID, 
     SalesDate, SalesTime, sum(productCost), sum(ShippingCost) 
FROM YOUR_TABLENAME 
GROUP BY left(CustomerID,4), salesdate, salestime 

什麼訂單號碼你想顯示?民?馬克斯?所有的EM?什麼?同樣的產品問題你想列舉產品還是隻是數一數?

Select count(*) as ProductsOnOrder, LEFT(CustomerID,4), as CID, 
     SalesDate, SalesTime, sum(productCost), sum(ShippingCost), 
     min(orderID), Max(orderID) 
FROM YOUR_TABLENAME 
GROUP BY left(CustomerID,4), salesdate, salestime 

既然您知道訂單上每一行的orderID是連續的,您可以返回最小值/最大值,並減去兩者以得到一個計數值。

+0

扣除MIN和MAX不起作用。如果某人刪除了其中一個訂單會怎麼樣?如果插入失敗並且事務回滾了,該怎麼辦? *將*已經存在的身份值已經消失。 –

+0

關鍵字可以。它確實假定數據尚未被刪除。我的實際答案是按需要的列進行計數和分組。 – xQbert

1

這應該會爲您提供NumOrders字段中該客戶/日期/時間的訂單數量。它使用我最喜歡的功能,Row_Number:

SELECT [CUSTOMERID], [SALESDATE], [SALESTIME], MAX(NumOrders) 
FROM (
    SELECT [CUSTOMERID], 
    [SALESDATE], 
    [SALESTIME], 
    ROW_NUMBER() OVER(PARTITION BY [CUSTOMERID], [SALESDATE], [SALESTIME] ORDER BY [CUSTOMERID]) AS NumOrders 
) t1 
GROUP BY [CUSTOMERID], [SALESDATE], [SALESTIME] 
+1

'ROW_NUMBER()'需要'ORDER BY',即使它沒有意義... –

+1

簡而言之,它儘可能地避免循環,因爲它非常耗費資源。 SQL喜歡對整個列(基於集合)進行操作,而不是行(基於行,或者ReBAR,通過Agonizing Row進行排序)。 –

+1

哎呀,謝謝@AaronBertrand。回答編輯。 –

1

我不認爲你需要一個循環在這裏。通常它被認爲是在sql中的一個不好的習慣,除非完全不可避免。你能否假定,如果一個訂單是由用戶在同一個日期時間完全屬於同一個邏輯訂單(訂單組)? 無論如何,整個問題大概可以用SQL server的partition and over clauses來解決。看看那裏的樣本D,我認爲它正在做一些你需要的東西。

EDIT
範圍子句availibale僅在SQL 2012,但仍可以通過使用簡單的計算(ROWNUMBER/4)上使用partioning和ROWNUMBER,然後組由烏爾結果返回ROWNUMBER

+0

謝謝。我現在正在查看分區和子句。我完成後會跟進。 – mikebmassey