0

我正在尝试获取事务数据并对其进行清理以满足我的分析需求。如何将事务记录到数据库中存在一些限制,我正在尝试绕过这些限制。

当客户下订单时包含超过 1 个产品,事务数据库不会将多个产品链接在一起。每个产品都有一个唯一的销售 ID,但无法将多个销售 ID 分组到 1 个订单中。这是一个示例:

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]。

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
4

4 回答 4

2

那么从这个陈述看来你想要这个:

我要确定的是每个订单运送的产品数量,以及总产品成本和运输成本。

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

所以我不确定你所说的使用 foreach 循环是什么意思?

更新:

使用子查询和上限函数让它工作

更新了小提琴

仅供参考的 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(作为浮点数)并使用上限函数四舍五入到最接近的 int 以将其分组为 4

于 2012-06-11T17:03:05.500 回答
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]
于 2012-06-11T16:55:53.187 回答
1

我认为您在这里不需要循环。通常它被认为是 sql 中的一种不好的做法,除非完全不可避免。您是否可以假设如果用户在同一日期时间下的订单恰好属于相同的逻辑订单(订单组)?无论如何,使用 SQL server 的partition 和 over 子句可能可以解决整个问题。看看那里的样本 D,我认为它正在做一些接近你需要的事情。

编辑
range 子句仅在 sql 2012 中可用,但是您仍然可以使用分区和行号,然后通过对返回的行号使用简单计算 (ROWNUMBER / 4) 按您的结果分组

于 2012-06-11T16:56:27.413 回答
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

您要显示什么订单号?敏?最大限度?全部?什么?关于产品的相同问题您要列出产品还是只计算它们?

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 对于订单上的每一行都是连续的,因此您可以返回 min/max 并将两者相减以获得计数。

于 2012-06-11T16:55:22.750 回答