加入两个数据不匹配的表

时间:2016-11-29 20:47:21

标签: sql tsql

我很难想出一个查询来完成连接两个数据不匹配的表。

我有两个共享相同项目和序列号列的表,但保存了我需要加入一个表的不同信息。问题是表A中销售的商品与表B中销售的商品不匹配。我需要做的是将表B中的位置排列到表A中我们仍然携带的商品。希望这有助于说明:

Table A                            Table B

a.Item | a.Serial                  b.Item | b.Serial | b.Sold | b.Location | b.WHSerial
x45      36-0004                   x45      36-0001    No       Rack1Bin2    WH0044
x45      36-0005                   x45      36-0002    No       Rack1Bin2    WH0045
x45      36-0006                   x45      36-0003    No       Rack1Bin2    WH0046
x45      36-0007                   x45      36-0004    No       Rack1Bin3    WH0047
y11      55-0110                   x45      36-0005    No       Rack1Bin3    WH0048
y11      55-0111                   x45      36-0006    Yes      N/A          WH0049
y11      55-0112                   x45      36-0007    Yes      N/A          WH0050
                                   y11      55-0109    No       Rack33Bin5   WH0122
                                   y11      55-0110    No       Rack33Bin5   WH0123
                                   y11      55-0111    No       Rack33Bin5   WH0124
                                   y11      55-0112    Yes      N/A          WH0125

期望输出

a.Item | a.Serial | b.Location | b.WHSerial
x45      36-0004    Rack1Bin3    WH0047
x45      36-0005    Rack1Bin3    WH0048
x45      36-0006    Rack1Bin2    WH0044
x45      36-0007    Rack1Bin2    WH0045
y11      55-0110    Rack33Bin5   WH0123
y11      55-0111    Rack33Bin5   WH0124
y11      55-0112    Rack33Bin5   WH0122

表A是主表,我需要将位置与每个序列号结合,但由于这种不匹配,我无法根据序列号加入。为了使其略微完成,表B中的某些项目的未售出序列号比表A中更多。表B中的任何额外未售出项目都可以忽略。

输出的逻辑是,如果表B中的匹配串行具有有效位置(不是N / A)那么它是好的,但如果没有,则有其他“未使用”的序列确实有效我要交换的地点。例如36-0006&表A中的36-0007未售出,但在表B中它们被出售并且具有无效的位置。如您所见,表B中的-0001到-0003在表A中没有匹配且具有有效位置。我想将这些位置用于-0006& -0007。从表B到表A的未使用的序列的分配可以是随机的,但它们需要保持唯一(如同,不要使用相同的未使用的串行两次)。

与b.Location一起,有一个相应的b.WHSerial需要在最终输出上。

3 个答案:

答案 0 :(得分:1)

<强> DEMO

首先计算未使用的位置并分配row_number。然后你会发现什么序列有一个匹配的位置,那些不是你的人也分配一个row_number。最后加入两者。所以未使用的位置只使用一次因为匹配rn。

WITH unusedLocation AS (
    SELECT B.[Item], B.[Serial], B.[Sold], B.[Location], A.[Serial] as [code],
           ROW_NUMBER() OVER (PARTITION BY B.[Item] ORDER BY B.[Location]) as rn
    FROM [TableB] B
    LEFT JOIN [TableA] A
    ON  A.[Item] = B.[Item]
    AND A.[Serial] = B.[Serial]    
    WHERE B.Location <> 'N/A'
      AND A.[Serial] IS NULL
), matchLocation AS (      
    SELECT A.[Item], A.[Serial], B.[Location],
           ROW_NUMBER() OVER (PARTITION BY B.[Location], A.[item] 
                              ORDER BY A.[Serial]) as rn       
    FROM [TableA] A
    LEFT JOIN [TableB] B 
    ON  A.[Item] = B.[Item]
    AND A.[Serial] = B.[Serial]    
    AND B.Location <> 'N/A'
)
SELECT M.Item, M.Serial, COALESCE (M.Location, U.Location) as Location
FROM matchLocation M
LEFT JOIN unusedLocation U
  ON M.Location IS NULL
 AND M.Item = U.Item
 AND M.rn = U.rn
ORDER BY M.Item, M.Serial;

<强>输出

第一张图片是您的输出,第二张是SELECT *,因此您可以看到部分结果。这个版本你必须partition by item所以重置为1。

enter image description here

答案 1 :(得分:0)

我们如何帮助您开始一些可以让您完成大部分工作的东西(命名N / A机架的逻辑我们不明白但是你去了: Select A.* ,Case When B.Location Not Like 'N/A' Then B.Location Else 'Rack1BinNA' End As Location From [Table A] A Left Join [Table B] B On A.Item = B.Item and A.Serial = B.Serial Where A.Sold = 'No'

答案 2 :(得分:0)

使用项目代码和序列号的LEFT OUTER JOIN是否可以解决这个问题?例如;

LEFT OUTER JOIN TableB ON TableA.Item = TableB.Item
AND TableA.Serial = TableB.Serial

然后,您应该能够从两个表中选择所需的列。