在SQL中查找类似的销售订单

时间:2017-06-26 03:45:57

标签: sql sql-server

这是我的第一篇文章。

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

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

以下是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

2 个答案:

答案 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

答案 1 :(得分: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