通过匹配孩子加入2个表

时间:2016-01-25 22:17:39

标签: sql-server join sql-server-2012

我试图拥有2张桌子(在这种情况下,它实际上是自助联接中的1张桌子)由他们匹配的孩子加入。

让我先说明这个目的,这可能会更好地理解我的需要:

我试图查找我刚刚收到的新订单,看看我们是否有相同的订单,以便找出打包的包装类型。 因此,我需要匹配订单才能包含相同的商品和相同的商品数量。

请查看下表并注意订单 1300981 与订单 1303097 具有相同的项目,如何编写此联接?

请记住:我不希望结果包含任何与%100不匹配的匹配项。

SQL Fiddle

OrderMain

| OrderID |  BoxId |
|---------|--------|
| 1300981 |     34 |
| 1303096 | (null) |
| 1303097 | (null) |
| 1303098 | (null) |
| 1303099 | (null) |
| 1303100 | (null) |
| 1303101 | (null) |
| 1303102 | (null) |
| 1303103 | (null) |
| 1303104 |     B1 |
| 1303105 | (null) |
| 1303106 | (null) |
| 1303107 |     48 |
| 1303108 | (null) |
| 1303109 | (null) |
| 1303110 | (null) |
| 1303111 | (null) |
| 1303112 | (null) |
| 1303113 | (null) |
| 1303114 | (null) |
| 1303115 | (null) |
| 1303116 | (null) |
| 1303117 | (null) |

Order Detail

| id | OrderID |   Item | Qty |
|----|---------|--------|-----|
|  1 | 1300981 | 172263 |   3 |
|  2 | 1300981 | 171345 |   3 |
|  3 | 1300981 | 138757 |   3 |
|  4 | 1303117 | 231711 |   1 |
|  5 | 1303116 | 227835 |   1 |
|  6 | 1303115 | 244798 |   1 |
|  7 | 1303114 | 121755 |   1 |
|  8 | 1303113 | 145275 |   2 |
|  9 | 1303112 | 219554 |   1 |
| 10 | 1303111 | 179385 |   1 |
| 11 | 1303110 |   6229 |   1 |
| 12 | 1303109 | 217330 |   1 |
| 13 | 1303108 | 243596 |   1 |
| 14 | 1303107 | 246758 |   1 |
| 15 | 1303106 | 193931 |   1 |
| 16 | 1303105 | 244659 |   1 |
| 17 | 1303104 | 192548 |   1 |
| 18 | 1303103 | 228410 |   1 |
| 19 | 1303102 | 147474 |   1 |
| 20 | 1303101 | 239191 |   1 |
| 21 | 1303100 | 243594 |   1 |
| 22 | 1303099 | 232301 |   1 |
| 23 | 1303098 | 201212 |   1 |
| 24 | 1303097 | 172263 |   3 |
| 25 | 1303097 | 171345 |   3 |
| 26 | 1303097 | 138757 |   3 |
| 27 | 1303096 | 172263 |   3 |
| 28 | 1303096 | 171345 |   1 |
| 29 | 1303096 | 138757 |   3 |
| 30 | 1303095 | 172263 |   3 |

预期结果

| OrderID |  BoxId |
|---------|--------|
| 1303097 |     34 |

2 个答案:

答案 0 :(得分:2)

执行此操作可能是一种奇怪的方式,但如果您将订单详细信息转换为xml并将其与其他订单进行比较,则可以查找匹配项。

WITH BoxOrders AS
(
    SELECT  om.[OrderId], 
            om.[BoxId],
            (SELECT Item, Qty 
             FROM orderDetails od 
             WHERE od.[OrderId] = om.[OrderId] 
             ORDER BY Item 
             FOR XML PATH('')) Details
    FROM    orderMain om
    WHERE   BoxID IS NOT NULL
)
SELECT mo.OrderId, bo.BoxId 
FROM   BoxOrders bo
JOIN (
    SELECT  om.[OrderId], 
            om.[BoxId],
            (SELECT Item, Qty 
             FROM orderDetails od 
             WHERE od.[OrderId] = om.[OrderId] 
             ORDER BY Item 
             FOR XML PATH('')) Details
    FROM    orderMain om
    WHERE   BoxID IS NULL
) mo ON bo.Details = mo.Details 

答案 1 :(得分:1)

SQL Fiddle

这是使用SQL和一些分析的不同方法。

这基于商品和数量和订单号<其他订单号并确保每个订单中的商品数量匹配。因此,如果项目匹配,计数匹配和数量匹配,则订单具有相同的项目。

这会返回两个订单,但很容易调整。使用CTE使计数具体化。很确定你不能使用像这样的分析。

我所做的一个主要假设是订单编号是连续的,当您说查看是否存在旧订单时,我只需要在评估先前订单是否具有相同项目时查看之前的订单编号和数量。

我还假设100%匹配意味着:完全相同的项目。相同数量的物品。和SAME项目计数,因此订单1的项目数为3,订单2为3,项目和数量匹配为100%,但如果订单2有4项,订单1只有​​3,则不匹配。

with cte as (
SELECT distinct OD1.OrderID PriorOrder, od2.orderID newOrder, OM.BoxId,
count(OD1.Item) over (partition by OD1.OrderID) OD1Cnt,
count(OD2.Item) over (partition by OD2.OrderID) OD2cnt
FROM OrderDetails OD1
INNER JOIN orderDetails OD2
 on OD1.item=OD2.item
 and od1.qty = od2.qty
 and OD1.OrderID < OD2.OrderID
LEFT JOIN ORderMain OM
 on OM.OrderID = OD1.orderID)
 Select PriorOrder, NewOrder, boxID from cte where od1cnt = od2cnt