2017-06-26 37 views
1

这是我的第一篇文章。在SQL中查找类似的销售订单

我在一家制造公司工作,我们制造的大部分产品都是定制的。 我们相信我们可以在我们销售的产品中找到一些共同点。

为此,我们需要分析销售订单并将其与我们系统中的所有销售订单进行比较以找到相同的订单。

下面是在SQL结果的形式的例子:

enter image description here

等等

+------------------------------+ 
| OrderId ProductCode Qty | 
+------------------------------+ 
| SS1234 Widget1  1 | 
| SS1234 Widget2  3 | 
| SS1234 Widget3  1 | 
+------------------------------+ 

我想找到同样的产品类似SS1234订单,即订单(widget1,widget2和widget3)和相同的数量。

如何在SQL Server 2008R2中执行此操作? 感谢您的帮助! Raf

+1

您的编辑使问题难以阅读。请向我们展示样本输入和您期望的输出,以及该输出背后的逻辑。 –

+0

所以像productcode = productcode和qty = qty和orderid!= orderid的自加入?或者有多少“小部件”需要匹配? – ZLK

+0

我可以看到你正在寻找匹配的确切数量和零件号码。但是在将来你可能想要扩展它来查看零件编号(颜色,重量等)的相似性。如果您想要更灵活的方法,请尝试查找余弦相似度 –

回答

0

在晚上睡觉之前我无法测试这个。这是一个过于详细的方法,但我想尽快研究出来,所以我尝试使用我熟悉的结构/语法,而不是试图编写更简洁,高效的代码,这需要我依赖文档。基本上,我们计算每个订单中的物品数量,每次找到两个匹配的订单项时选择一对订单ID,然后我们计算一个确切的订单ID对出现的次数。使用内部联接来筛选比订单中的产品少的次数的匹配对。

WITH 
ProductCounts AS (
SELECT COUNT(OrderID) AS ProductCodesInOrder, OrderID 
FROM Table 
GROUP BY OrderID 
), MatchingLineItems AS (
SELECT A.OrderID AS FirstOrderID, B.OrderID AS SecondOrderID 
FROM Table AS A 
INNER JOIN Table AS B 
ON A.ProductCode = B.ProductCode AND A.Qty = B.Qty 
ORDER BY FirstOrderID, SecondOrderID 
), MatchTotals AS (
SELECT 
COUNT(FirstOrderID) AS Matches, FirstOrderID, SecondOrderID 
FROM MatchingLineItems 
GROUP BY FirstOrderID, SecondOrderID 
), FirstMatches AS (
SELECT MatchTotals.FirstOrderID, MatchTotals.SecondOrderID, MatchTotals.Matches 
FROM MatchTotals 
INNER JOIN ProductCounts 
ON MatchTotals.FirstOrderID = ProductCounts.OrderID 
WHERE MatchTotals.Matches = ProductCounts.ProductCodesInOrder 
) 
SELECT FirstMatches.FirstOrderID, FirstMatches.SecondOrderID 
FROM FirstMatches 
INNER JOIN ProductCounts 
ON FirstMatches.SecondOrderID = ProductCounts.OrderID 
WHERE FirstMatches.Matches = ProductCounts.ProductCodesInOrder 
0

设置:

CREATE TABLE #ord (
    OrderId VARCHAR(20), 
    ProductCode VARCHAR(40), 
    qty int 
) 
INSERT INTO #ord (OrderId, ProductCode, Qty) 
VALUES 
    ('SS1234','Widget1',1) 
,('SS1234','Widget2',3) 
,('SS1234','Widget3',1) 

,('SS1234a','Widget1',1) 
,('SS1234a','Widget2',3) 
,('SS1234a','Widget3',1) 

,('xSS1234','Widget1',1) 
,('xSS1234','Widget2',3) 
,('xSS1234','Widget3',1) 
,('xSS1234','Widget4',1) 

,('ySS1234','Widget1',10) 
,('ySS1234','Widget2',3) 
,('ySS1234','Widget3',1) 

,('zSS1234','Widget2',3) 
,('zSS1234','Widget3',1) 
; 

查询:

with CTE as (
    select distinct 
     o.OrderID, ca.ProductString, ca.QtyString 
    from #ord o 
    cross apply (
     SELECT 
      STUFF((
        SELECT 
         ', ' + o2.ProductCode 
        FROM #ord o2 
        WHERE o.OrderID = o2.OrderID 
        ORDER BY o2.ProductCode 
        FOR XML PATH ('') 
       ) 
       , 1, 1, '') 
      , STUFF((
        SELECT 
         ', ' + cast(o2.Qty as varchar) 
        FROM #ord o2 
        WHERE o.OrderID = o2.OrderID 
        ORDER BY o2.ProductCode 
        FOR XML PATH ('') 
       ) 
       , 1, 1, '') 
     ) ca (ProductString, QtyString) 
    ) 
select 
    ProductString, QtyString, count(*) Num_Orders 
from CTE 
group by 
    ProductString, QtyString 
having 
    count(*) > 1 
order by 
    Num_Orders DESC 
    , ProductString 

结果:

ProductString    QtyString Num_Orders 
Widget1, Widget2, Widget3 1, 3, 1  2 

请参阅:http://rextester.com/DJEN59714

相关问题