2013-08-01 2 views
1

Использование синтаксиса SQL Server T-SQL, как вы можете найти все записи в течение последнего месяца транзакции для конкретного клиента?Выделить все записи за последний месяц

Учитывая следующие записи:

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 

Выходной сигнал запроса должен выглядеть следующим образом:

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

лучшим, что я придумал такой запрос (не проверено), который выглядит ужасно неэффективно.

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 
) 
+0

Concat? В самом деле? –

+1

'WHERE [TRANSACTION_DATE]> = DATEADD (mm, DATEDIFF (mm, 0, GETDATE()) - 1,0) AND [TRANSACTION_DATE]

+0

@ Тит, пожалуйста, не сокращайте - просто укажите его как« МЕСЯЦ ». Чтобы понять, почему, посмотрите, какие 'y' и' w' делают. :-) –

ответ

1
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) 

Я уезжаю выше для справки.

я пришел к следующему:

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 

, который очень похож на Романа. Разница в том, что у меня есть равенство, а не больше. План выполнения выглядит лучше, и именно поэтому я его публикую.

У меня есть here скрипка из всех, но все-таки первое, что кажется, первое в истории.

+0

Этот тип самоподключения является проблематичным с точки зрения чтения. В него также войдут строки из других лет, которые были в том же месяце. –

+0

Я думаю, все зависит от того, сколько данных есть –

+0

Конечно, но зачем использовать метод, который, как гарантируется, будет иметь высокий уровень чтения? Просто потому, что данные могут быть небольшими, теперь для этого OP это не будет иметь место для всех. –

2
;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 

SQL FIDDLE EXAMPLE

другой способ сделать это:

;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 

SQL FIDDLE EXAMPLE

+1

Я не думаю, что это дает запрошенные результаты. Он получает последнюю запись каждого месяца, но ему предлагается получить все записи за последний месяц. –

+0

проклятый пропустил это, подождать секунд –

+0

сменить запрос –

Смежные вопросы