TSQL - 记录子集的完全匹配

时间:2014-07-08 12:12:52

标签: sql sql-server tsql

我有以下表结构和数据

TransID   TransType  Product  Qty  OrderRef  Date
-------   ---------  -------  ---  --------  ----
C123      Credit     Prod1    1     Order8   2014-07-08
C123      Credit     Prod2    5     Order8   2014-07-08
Inv111    Invoice    Prod1    1     Order8   2014-07-08
Inv111    Invoice    Prod2    5     Order8   2014-07-08
C999      Credit     Prod1    6     Order8   2014-07-08
C999      Credit     Prod2    9     Order8   2014-07-08
Inv666    Invoice    Prod1    6     Order8   2014-07-08

我想要做的是能够识别那些具有完全匹配的发票记录组的信用记录。通过完全匹配,我的意思是相同的Product,OrderRef,Qty和Date

在上面的数据中,C123会与Inv111匹配,但C999与Inv666不匹配,因为Inv666缺少一行

我想要删除具有完全匹配的Credit和Invoice记录。除了OrderRef

之外,Invoice和Credits之间没有任何关联

我玩过Except语句,如下所示: -

    ;with CreditToInvoice(Product, Qty, OrderRef, Date)
as
    (select Product
                    ,Qty
                    ,OrderRef
                    ,Date)
        from @t t1
        where t1.TransType = 'Credit'
        group by TransactionID, OrderRef, Product, Date, Qty

        EXCEPT

        select Product
                      ,Qty
                      ,OrderRef
                      ,Date)
        from @t t2
        where t2.TransType = 'Invoice'
        group by TransactionID, OrderRef, Product, Date, Qty
    )

它给了我表格中的所有内容,而不是表格b,正如我所期待的那样

问题是我真的需要TransactionID,以便我可以继续正确删除

除此之外的错误陈述是什么?我可以使用合并吗?

非常感谢任何帮助

4 个答案:

答案 0 :(得分:1)

我认为LEFT JOIN和某些GROUP是处理此要求的最明显方式:

SELECT
    cr.TransID,
    MAX(inv.TransID) as InvoiceID,
    MAX(CASE WHEN inv.TransID is NULL THEN 1 ELSE 0 END) as Unsatsified
FROM
    @t cr
       left join
    @t inv
       on
           cr.Product = inv.Product and
           cr.OrderRef = inv.OrderRef and
           cr.Qty = inv.Qty and
           cr.Date = inv.Date and
           inv.TransType = 'Invoice'
WHERE
    cr.TransType = 'Credit'
GROUP BY
    cr.TransID
HAVING
    MAX(CASE WHEN inv.TransID is NULL THEN 1 ELSE 0 END) = 0

也就是说,我们将信用卡和发票之间的所有匹配行连接在一起,然后我们只在所有信用行达到匹配时才选择此结果。

如果您需要在单个列中同时使用TransID个值来处理下一部分,则可以将其放在子查询或CTE中并执行取消操作。

答案 1 :(得分:1)

生成的TransID应该是您需要删除的

DECLARE  @Trans TABLE
    ([TransID] varchar(6), [TransType] varchar(7), [Product] varchar(5), [Qty] int, [OrderRef] varchar(6), [Date] datetime)
;

INSERT INTO @Trans
    ([TransID], [TransType], [Product], [Qty], [OrderRef], [Date])
VALUES
    ('C123', 'Credit', 'Prod1', 1, 'Order8', '2014-07-08 00:00:00'),
    ('C123', 'Credit', 'Prod2', 5, 'Order8', '2014-07-08 00:00:00'),
    ('Inv111', 'Invoice', 'Prod1', 1, 'Order8', '2014-07-08 00:00:00'),
    ('Inv111', 'Invoice', 'Prod2', 5, 'Order8', '2014-07-08 00:00:00'),
    ('C999', 'Credit', 'Prod1', 6, 'Order8', '2014-07-08 00:00:00'),
    ('C999', 'Credit', 'Prod2', 9, 'Order8', '2014-07-08 00:00:00'),
    ('Inv666', 'Invoice', 'Prod1', 6, 'Order8', '2014-07-08 00:00:00')
;

DECLARE  @TransUnique TABLE
    ([TransID] varchar(6)
)

INSERT INTO @TransUnique
    SELECT DISTINCT TransID FROM @Trans

--Remove Credits
DELETE t
FROM @TransUnique t
INNER JOIN (
    select t1.*,t2.TransID [TransId2],t2.TransType [TransType2]
    From @Trans t1
    LEFT JOIN  @Trans t2 ON t1.OrderRef=t2.OrderRef
        AND t1.Date=t2.Date
        AND t1.Qty=t2.Qty
        AND t1.Product=t2.Product
        AND t2.TransType='Invoice'
    WHERE t1.TransType='Credit'
) joined ON t.TransID=joined.TransId AND joined.TransId2 IS NULL

--Remove Invoices
DELETE t
FROM @TransUnique t
INNER JOIN (
    select t1.*,t2.TransID [TransId2],t2.TransType [TransType2]
    From @Trans t1
    LEFT JOIN  @Trans t2 ON t1.OrderRef=t2.OrderRef
        AND t1.Date=t2.Date
        AND t1.Qty=t2.Qty
        AND t1.Product=t2.Product
        AND t2.TransType='Invoice'
    LEFT JOIN @TransUnique tu ON tu.TransID=t1.TransID
    WHERE t1.TransType='Credit'
    AND tu.TransID IS NULL
) joined ON t.TransID=joined.TransId2

SELECT * FROM @TransUnique

答案 2 :(得分:0)

如果我正确地读到这个,这样的事情应该有用。

select TransID, TransType, Product, Qty, OrderRef, Date from @t t1
where t1.TransType = 'Credit'
and exists (
    select 1 from @t t2
    where t2.TransType = 'Invoice'
    and t2.Product = t1.Product
    and t2.Qty = t1.Qty
    and t2.OrderRef = t1.OrderRef
    and t2.Date = t1.Date
)

答案 3 :(得分:0)

试试这个以获得transid

Select TransId
From @t t1
join @t t2 
on t1.transtype = 'Credit' and t2.transtype = 'Invoice' 
and  t1.product=t2.product and t1.qty = t2.qty 
and t1.orderef=t2.orderref and t1.date = t2.date