2017-06-26 48 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

相關問題