Reputation: 169
Using SQL Server T-SQL syntax how can you find all records within the last/max transaction month for a specific customer?
Given the following records:
CUSTOMER_ID | TRANSACTION_DATE
------------------------------
00001 | 04/21/2013
00001 | 05/01/2013
00001 | 05/14/2013
00002 | 06/08/2013
00002 | 07/01/2013
00002 | 07/28/2013
The output of the query should look like:
CUSTOMER_ID | TRANSACTION_DATE
------------------------------
00001 | 05/01/2013
00001 | 05/14/2013
00002 | 07/01/2013
00002 | 07/28/2013
The best I've come up with is this query (not tested), which looks horribly inefficient.
select customer_id, transaction_date
from customer_table outer
where concat(month(transaction_date), year(transaction_date)) = (
select concat(month(max(transaction_date)), year(max(transaction_date)))
from customer_table inner
where outer.customer_id = inner.customer_id
)
Upvotes: 1
Views: 1514
Reputation: 18411
SELECT T1.*
FROM Table1 T1
JOIN
(
SELECT CUSTOMER_ID,
MAX(TRANSACTION_DATE) AS TRANSACTION_DATE
FROM Table1
GROUP BY CUSTOMER_ID
) T2
ON T1.CUSTOMER_ID = T2.CUSTOMER_ID
WHERE MONTH(T1.TRANSACTION_DATE) = MONTH(T2.TRANSACTION_DATE)
AND YEAR(T1.TRANSACTION_DATE) = YEAR(T2.TRANSACTION_DATE)
I am leaving the above for reference.
I have come to the following:
WITH MyCTE AS
(
SELECT [CUSTOMER_ID],
MAX(DATEADD(month, DATEDIFF(month, 0, [TRANSACTION_DATE]), 0)) AS StartOfMonth
FROM Table1
GROUP BY [CUSTOMER_ID]
)
SELECT T2.*
FROM MyCTE M
Join Table1 T2
ON DATEADD(month, DATEDIFF(month, 0, [TRANSACTION_DATE]), 0) = StartOfMonth
Which is very similar to the Roman's. The difference is that i have an equality rather than greater than. The execution plan seems better, and that is why i post it.
I have here the fiddle of all, but still Roman's first seems to be the best.
Upvotes: 1
Reputation: 117337
;with CTE as (
select
customer_id, transaction_date,
rank() over(
partition by customer_id
order by year(transaction_date) desc, month(transaction_date) desc
) as row_num
from customer_table
)
select *
from CTE
where row_num = 1
another way to do it:
;with CTE as (
select
customer_id, dateadd(month, datediff(month, 0, max(transaction_date)), 0) as date
from @customer_table
group by customer_id
)
select ct.*
from CTE as c
inner join @customer_table as ct on
ct.transaction_date >= c.date and ct.customer_id = c.customer_id
Upvotes: 2