I am not a SQL guy, I have used it in the past and rarely have an issue that cant be solved by google... however this time I need to ask the Community.
I have a database
You can use a CTE and the ranking function PARTITION BY
:
WITH CTE AS
(
select t.ProdNo, t.TransactionDate as 'LastPurchaseDate', t.Price,
rn = row_number() over (partition by ProdNo order by TransactionDate desc)
from Transactions t
)
SELECT ProdNo, LastPurchaseDate, Price FROM CTE WHERE RN = 1
Try this. by using row_number().
select * from
(
select
T.ProdNo,
T.TransactionDate as 'LastPurchaseDate',
T.Price,
row_number() over (partition by ProdNo order by TransactionDate desc) as rnk
from Transactions T
)a
where rnk='1'
SELECT A.ProdNo ,Price ,A.TransactionDate,PurchasedBy
FROM #Transactions
JOIN
(
SELECT ProdNo,MAX(TransactionDate) TransactionDate
FROM #Transactions
GROUP BY ProdNo
)A ON A.TransactionDate = #Trans.TransactionDate
Pls Try this --If one ProdNo has two same max TransactionDate, will return both two rows
select ProdNo,Price,TransactionDate from Transactions t
where not exists (select 1 from Transactions where ProdNo=t.ProdNo and TransactionDate>t.TransactionDate)
You're on the right track. What if you use:
select t.ProdNo, t.TransactionDate as 'LastPurchaseDate', t.Price
from Transactions t
inner join (
select ProdNo, max(TransactionDate) as 'LastPurchaseDate'
from Transactions
WHERE Price > 0
group by ProdNo
) tm on t.ProdNo = tm.ProdNo and t.TransactionDate= tm.LastPurchaseDate
Note the change in join conditions.
What happened in your query: LastPurchaseDate = tm.LastPurchaseDate
. There is only one column called LastPurchaseDate
, so it's equating it with itself, which is always true. So you're left with t.ProdNo = tm.ProdNo
, since t.ProdNo
is not unique, you get multiple records returned for each t.ProdNo
.
One method uses the ROW_NUMBER windowed function.
My query uses a common table expression (CTE) to provide sample data. When using this technique you always need a CTE, or subquery. This is because values generated in the SELECT clause are not available to the WHERE clause. This is a consequence of something called the Logical Processing Order. In other words; SQL Server generates the row numbers after it has filtered the data. CTEs/Subqueries provide you with a second WHERE clause, that is actioned after the row numbers have been generated**.
-- Returning the most recent record from a transaction table.
WITH SampleDate AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY ProdNo ORDER BY TransactionDate DESC) AS Rn,
*
FROM
(
VALUES
('3STRFLEX', 13.02, '20162911', 'AWC '),
('3STRFLEX', 15.02, '20162011', 'DWC '),
('3STRFLEX', 15.02, '20160101', 'AWC '),
('AFTV2' , 35.49, '20162708', 'AWC '),
('AFTV2' , 29.99, '20160106', 'DWC '),
('AFTV2' , 29.99, '20160205', 'AWC ')
) AS x(ProdNo, Price, TransactionDate, PurchasedBy)
)
SELECT
*
FROM
SampleDate
WHERE
Rn = 1
;
** Actually this isn't entirely true. It is called the logical order for a reason. SQL Sever can/will exeucte your queries any way it sees fit. But however your query is physically executed it will respect the logical order.