sql排除偏移行

时间:2016-12-14 16:09:26

标签: sql sql-server

在下面的查询中,如果有另一行具有相同的作业ID和相反的发票总额,我想排除任何行(供应商发票)。例如,如果作业1234具有-10,10和20的供应商发票,则在查询结果中只应返回值为20的那个。理想情况下,如果作业的发票金额为-10,10,10和20,则结果应返回20发票和10张最早发票日期的发票。

SELECT  J.JobID,
   VI.VendorInvoiceNo,
   VI.invoicetotal,
   VI.importedDate,
   VI.CreationDate,
   VI.InvoiceDate

FROM  VendorInvoices AS VI
   LEFT JOIN Jobs AS J ON J.JobID = VI.JobID

WHERE  J.operCompleteDate >= (GETDATE()-90)
   AND VI.invoicetotal IS NOT NULL
   AND VI.invoicetotal <> 0

2 个答案:

答案 0 :(得分:3)

您的查询基本上是:

SELECT vi.*
FROM VendorInvoices vi LEFT JOIN
     Jobs J
     ON J.JobID = VI.JobID
WHERE J.operCompleteDate >= (GETDATE()-90) AND
      vi.invoicetotal IS NOT NULL
      vi.invoicetotal <> 0;

如果我们将其用作CTE:

WITH vi as (
      SELECT vi.*
      FROM VendorInvoices vi LEFT JOIN
           Jobs J
           ON J.JobID = VI.JobID
      WHERE J.operCompleteDate >= (GETDATE()-90) AND
            vi.invoicetotal IS NOT NULL
            vi.invoicetotal <> 0
     )
SELECT vi.*
FROM vi
WHERE NOT EXISTS (select 1
                  from vi vi2
                  where vi2.jobid = vi.jobid and
                        vi2.invoicetotal = - vi.invoicetotal
                 );

答案 1 :(得分:0)

无需为此使用CTE。这只会增加开销。只需在查询中两次引用该表。

SELECT  
    J.JobID,
    VI.VendorInvoiceNo,
    VI.invoicetotal,
    VI.importedDate,
    VI.CreationDate,
    VI.InvoiceDate

FROM  VendorInvoices AS VI
INNER JOIN Jobs AS J        -- Since operCompleteDate must exist, use INNER JOIN
    ON J.JobID = VI.JobID
LEFT JOIN VendorInvoices filter
    ON filter.JobID = VI.JobID
    AND filter.InvoiceTotal = -(VI.InvoiceTotal)
WHERE  J.operCompleteDate >= (GETDATE()-90)
   AND VI.invoicetotal IS NOT NULL
   AND filter.invoiceTotal IS NOT NULL
   AND VI.invoicetotal <> 0

JobID和InvoiceTotal上的索引将确保最大处理速度,但可能没有必要。