Reputation: 1
I am fairly new to SQL and am looking for a solution. I am looking to find the best way to get the newest date from transaction date while being grouped by Job reference. Since these are different tables I am struggling someone please help.
SELECT
C.CustomerCode,
C.name AS Customer,
B1.Name AS 'Customer Home Branch',
B.Name AS 'Trx Branch',
At.DocumentNumber AS 'Document
Number',
At.TransactionDate AS 'Document
Date',
At.PaymentDueDate AS 'Due Date',
CASE
WHEN At.TransactionType = 1 THEN 'Invoice'
WHEN at.transactiontype = 2 THEN 'CreditNote'
WHEN at.transactiontype = 3 THEN 'FC'
WHEN AT.transactiontype = 4 THEN 'Payment'
WHEN At.TransactionType = 8 THEN 'Adj'
ELSE ''
END AS Type,
CA.AddressCode,
J.JobReference,
At.OriginalAmount AS 'Original
Amount',
At.AmountOutstanding AS 'Outstanding Amount',
DATEDIFF(DAY, AT.PaymentDueDate, GETDATE()) AS 'Days Past Due',
DATEDIFF(DAY, At.TransactionDate, GETDATE()) AS 'Days From Shipment',
C.customerID,
AT.AccountsTransactionID
FROM
AccountsTransaction AS AT WITH (NOLOCK)
LEFT JOIN
Customer AS C WITH(NOLOCK) ON C.customerid = AT.CustomerID
LEFT JOIN
Branch AS B WITH(NOLOCK) ON B.branchid = AT.BranchID
LEFT JOIN
Branch AS B1 WITH(NOLOCK) ON B1.branchid = C.HomeBranchID
LEFT JOIN
CustomerAddress AS CA WITH(NOLOCK) ON CA.customerAddressID = AT.DeliveryAddressID
LEFT JOIN
Job AS J WITH(NOLOCK) ON j.jobID = CA.JobID
Please help!! I am having a very hard time using a max and group by with so many tables being joined above. I would like to group by job reference and show the newest transaction date in this manner.
INNER JOIN
(SELECT
AT.DeliveryAddressID,
MAX('TransactionDate') AS ND
FROM
AccountsTransaction AS AT
GROUP BY
AT.DeliveryAddressID) AS New ON AT.DeliveryAddressID = J.JobID
Upvotes: 0
Views: 55
Reputation: 35603
Without looking too deeply at your query, and in the absence of any sample data, I suggest you use row_number() over()
to locate the most recent transaction, and then filter by (or in a join condition) the generated row numbers (column rn
below):
SELECT
*
FROM (
SELECT
CustomerID
, DocumentNumber
, TransactionDate
, PaymentDueDate
, CASE
WHEN TransactionType = 1 THEN 'Invoice'
WHEN transactiontype = 2 THEN 'CreditNote'
WHEN transactiontype = 3 THEN 'FC'
WHEN transactiontype = 4 THEN 'Payment'
WHEN TransactionType = 8 THEN 'Adj'
ELSE ''
END AS Type
, OriginalAmount
, AmountOutstanding
, DATEDIFF(DAY, PaymentDueDate, GETDATE()) AS DayePastDue
, DATEDIFF(DAY, TransactionDate, GETDATE()) AS DaysFromShipment
, AccountsTransactionID
, ROW_NUMBER() OVER(PARTITION BY CustomerID
ORDER BY TransactionDate DESC) AS rn
FROM AccountsTransaction
-- nb: you cannot filter by ROW_NUMBER here, it has to be later as seen below
) AS atran
WHERE atran.rn = 1
The OVER
clause partitions the data by customerid
(PARTITION BY
is similar to a GROUP BY
clause). Within each partition, the data is ordered by TransactionDate
in descending order. Then the ROW_NUMBER()
function assigns a number to each row, starting with 1 which will be the most recent date and increments by 1 for each subsequent row. When a new customerid
is encountered, the row numbering restarts at 1.
You can apply this in your existing select clause but using J.JobReference
as the partiioning column, but note you must add another "layer" to the query to do the "where rn = 1" so you may want to avoid including all the column aliases until you reach the outermost query layer.
SELECT
*
FROM (
SELECT
J.JobReference,
, AT.AccountsTransactionID
, ROW_NUMBER() OVER(PARTITION BY J.JobReference
ORDER BY at.TransactionDate DESC) AS rn
, B1.Name AS b1Name
...
FROM AccountsTransaction AS AT WITH (NOLOCK)
LEFT JOIN Customer AS C ON C.customerid = AT.CustomerID
LEFT JOIN Branch AS B ON B.branchid = AT.BranchID
LEFT JOIN Branch AS B1 ON B1.branchid = C.HomeBranchID
LEFT JOIN CustomerAddress AS CA ON CA.customerAddressID = AT.DeliveryAddressID
INNER JOIN Job AS J ON j.jobID = CA.JobID
) AS d
WHERE rn = 1
nb: I suggest you would not use a left join if job numbers are vital to the query...
Upvotes: 0