2012-04-10 2 views
2

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

FirstEvent     LastEvent    Client 
== 
2011-01-01 06:55:21.000 |2011-04-30 21:46:09.000 |Client1 
2011-01-01 06:20:00.000 |2011-02-23 12:43:55.000 |Client2 
2011-01-03 08:34:33.000 |2011-04-30 09:00:39.000 |Client3 
2011-01-01 02:14:45.000 |2011-04-30 15:31:41.000 |Client4 
2011-01-01 08:08:12.000 |2011-02-21 09:41:28.000 |Client5 
2011-02-01 11:29:28.000 |2011-04-29 09:13:25.000 |Client6 

Теперь я должен считать записи каждого клиента и сгруппировать их, как этот

Client  From     To      Records 
== 
Client1 |2011-04-30 21:46:09.000 |2011-04-23 21:46:09.000 |200 
Client1 |2011-04-16 21:46:09.000 |2011-04-09 21:46:09.000 |400 
           ...Until the the first date 
Client1 |2011-01-08 06:55:21.000 |2011-01-01 06:55:21.000 |250 
Client2 |2011-02-23 12:43:55.000 |2011-02-16 12:43:55.000 |50 
           ...The same for each user 

Я надеюсь, что кто-то может помочь мне найти путь к выходу этого.

ответ

1

Хорошо, я думаю, что это делает именно то, что вы хотите:

SELECT CONVERT(datetime, '2011-01-01 06:55:21.000', 120) AS event, 'client1' AS Client 
INTO #EVENTS 
UNION ALL SELECT '2011-01-08 06:55:20.000', 'client1' 
UNION ALL SELECT '2011-04-30 21:46:09.000', 'client1' 


;WITH E AS (
    SELECT 
     Client, 
     MIN(event) AS FirstEvent 
    FROM #EVENTS 
    GROUP BY Client 
) 
,B AS (
    SELECT 
     E.Client, 
     E.FirstEvent, 
     COUNT(*) AS Records, 
     DATEDIFF(DAY, 0, c.event - E.FirstEvent)/7 AS [weeks]  
    FROM #EVENTS c 
    JOIN E ON E.Client = c.Client 
    GROUP BY E.Client, E.FirstEvent, DATEDIFF(DAY, 0, c.event - E.FirstEvent)/7 
) 
SELECT 
    Client, 
    DATEADD(WEEK, weeks, FirstEvent) AS [From], 
    DATEADD(WEEK, weeks + 1, FirstEvent) AS [To], 
    Records 
FROM B 
ORDER BY Client, weeks; 

DROP TABLE #EVENTS 

Хотя, если нет записей определенной недели, он выйдет из этой строки вместо возврата строки, содержащей Записи значение 0:

Edit:

Если вам интересно, почему я использую DAY вместо WEEK для моего DATEDIFF, чтобы избежать проблем, будет ли воскресенье или понедельник первым днем ​​недели.

+0

Я приспосабливаюсь к моему сценарию и тестирую сейчас. Ty –

+0

Я удалил его, поскольку он не нужен. Вывод не содержит LastEvent, и только FirstEvent необходим как неделя «origo». Но весь фрагмент кода является примером, поэтому вы можете просто скопировать его и попробовать. – ANisus

+0

Хорошо, я понял. И мне понравился подход дня. Он работает отлично с моими данными. если вы не возражаете, не могли бы вы указать мне, что мне нужно изменить, чтобы я мог получить обратное? Начиная с последнего события, до первого. –

2

Вы можете группировать по неделям, используя функцию DATEDIFF.

SELECT e.[Client] 
, [From] = MIN(e.EventDate) 
, [To] = MAX(e.EventDate) 
, [Records] = COUNT(*) 
FROM Events AS e 
GROUP BY e.[Client] 
, DATEDIFF(week, '1900-01-01', e.EventDate) 
+0

Я думаю, что Данило хочет отделять недели от FirstEvent как своего рода ориго, а не фактические недели (1900-01-01). Но в остальном - чистый и простой ответ. – ANisus

+0

Вы должны добавить столбец 'e. [Client]' в предложение GROUP BY. –

+0

@Bogdan Совершенно верно. Я обновил код. –

0

Это должно работать, если количество недель между началом и концом меньше 2048, если нет, то я бы предложил использовать таблицу чисел.

SELECT 
client 
,DATEADD(WK,(number * -1) -1,fromdate) as [from] 
,DATEADD(WK,number * -1,fromdate) as [to] 
,COUNT(client) as records 
from #sample 
LEFT OUTER JOIN (SELECT number FROM dbo.spt_values WHERE type = 'p') nums 
on nums.number <= DATEDIFF(WK,todate,fromdate) 
GROUP BY client 
,DATEADD(WK,(number * -1) -1,fromdate) 
,DATEADD(WK,number * -1,fromdate) 
ORDER BY 
client 
,DATEADD(WK,(number * -1) -1,fromdate) DESC 
Смежные вопросы