Sélectionner tous les loggings au cours du dernier mois

À l'aide de la syntaxe SQL Server T-SQL, comment pouvez-vous find tous les loggings dans le mois de transaction dernier / maximum pour un client spécifique?

Compte tenu des loggings suivants:

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 

La sortie de la requête devrait ressembler à ceci:

 CUSTOMER_ID | TRANSACTION_DATE ------------------------------ 00001 | 05/01/2013 00001 | 05/14/2013 00002 | 07/01/2013 00002 | 07/28/2013 

Le meilleur que j'ai trouvé est cette requête (non testée), qui est horriblement inefficace.

 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 ) 

 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) 

Je laisse le dessus pour reference.

Je suis arrivé à ce qui suit:

 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 

Ce qui est très similaire à celui de Roman. La différence est que j'ai une égalité plutôt que de plus. Le plan d'exécution semble mieux, et c'est pourquoi je l'affiche.

J'ai ici le violon de tous, mais le premier de Roman semble être le meilleur.

 ;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 

Exemple SQL FIDDLE

une autre façon de le faire:

 ;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 

Exemple SQL FIDDLE