TSQL-记录子集上的精确匹配

TSQL-记录子集上的精确匹配,sql,sql-server,tsql,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

我有下表的结构和数据

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
我想做的是能够识别那些具有精确匹配的发票记录组的信用记录。精确匹配指的是相同的产品、OrderRef、数量和日期

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

我想删除完全匹配的信用记录和发票记录。除了OrderRef之外,发票和信用证之间没有链接

我一直在玩弄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
    )
这给了我表a中的所有内容,而不是我所期望的表b中的所有内容

问题是我真的需要TransactionID,这样我才能继续正确地删除


这句话的意思是错误的吗?我可以使用合并吗?

如果我读对了,像这样的东西应该可以用

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
)

试试这个,以获得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

我认为
左连接
和一些
ing是处理此要求的最明显的方法:

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中并执行unpivot。

生成的TransID应该是需要删除的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

我假设如果发票与信用证之间有额外的一行,您也不想声明匹配?这样的数据可能存在吗?对不起,我应该指定。如果有额外的发票行,我不会大惊小怪的。只要发票涵盖了信用,发票是否有更多的争议就无关紧要。当我将其标记为答案时,您删除了您的帖子?我不相信它涵盖了100%的角落案例,但我不确定您的数据中是否存在此类角落。我想再考虑一下这个问题。达米恩,出于好奇,如果我想更进一步,说是的-发票行必须与信用行的计数相匹配,这很重要,我该如何调整?哦,但是你需要每个TransID的所有行都匹配。。。这个不行。