Reputation: 31
In the query below, I would like to exclude any rows (vendor invoices) if there is another row with the same job ID and an opposite invoice total. For example, if job 1234 has vendor invoices in the amounts of -10, 10, and 20, then only the one with a value of 20 should be returned in the query results. Ideally, if a job has invoices in the amounts of -10, 10, 10, and 20, then the results should return the 20 invoice and the 10 invoice with the oldest invoice date.
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
Upvotes: 3
Views: 75
Reputation: 3756
No need to use a CTE for this. That just adds overhead. Simply refer to the table twice in the query.
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
An index on JobID and InvoiceTotal will ensure maximum processing speed, but may not be necessary.
Upvotes: 0
Reputation: 1270483
Your query is basically:
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;
If we use this as a 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
);
Upvotes: 3