我正在尝试获取事务数据并清理它以满足我的分析需求。如何将事务记录到数据库中有一些限制,我试图绕过这些限制。
当客户下订单超过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个订单。如果orderID是范围中的第5到第8个订单,那么那是第2批货物等等。
这可以在SQL Server
完成吗?如果不是这样,我该怎么写呢?在这种情况下我应该使用for-loop
吗?
编辑:这是我想要的输出。请记住,在第4个产品发货后,我需要重新开始订购(因此,6个产品分为2个出货[4个产品和2个产品],9个产品分为3个出货[4,4和1]。 / p>
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 :(得分:2)
从这句话来看,似乎你想要这个:
我想确定的是每个产品的出货数量 订单,以及总产品成本和运输成本。
http://sqlfiddle.com/#!3/e0e71/30
所以我不确定你使用foreach循环是什么意思?
更新:
使用子查询和天花板功能
更新了小提琴
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(作为float)并使用ceiling函数向上舍入到最近的int以将其分组为4
答案 1 :(得分: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]
答案 2 :(得分:1)
我不认为你需要一个循环。通常它被认为是sql中的一种不好的做法,除非完全不可避免。您是否可以假设,如果用户在同一日期时间完成订单,则该订单属于同一逻辑订单(订单组)? 无论如何,整个问题可以使用SQL服务器partition and over clauses来解决。看那里的样本D,我认为它做的很接近你需要的东西。
修改强>
range范围只在sql 2012中可用,但是你仍然可以使用partioning和rownumber,然后通过在返回的rownumber上使用简单计算(ROWNUMBER / 4)按结果分组
答案 3 :(得分: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对订单中的每一行都是连续的,您可以返回最小值/最大值并减去这两行以获得计数。