2013-05-02 2 views
1

У вас есть таблица в sql server 2008, в которой захватываются посещения страниц, что-то похожее на журналы IIS или Google Analytics, ничего необычного.Выберите и запишите группы за 30 минут друг от друга

В таблице есть столбцы, такие как:

[ID], [Имя пользователя], [URL], [Создано], [Браузер], [BrowserVersion], [HostName], [IP-адрес], [OperatingSystem] , [UrlReferrer]

Внизу снимок проиллюстрирован вывод запроса, отсортированный по дате создания (созданный столбец) в нисходящем формате, представляющий/перечисляющий все образы страниц. URL-адреса и имена пользователей опущены для целей конфиденциальности.

Query

То, что я хотел бы сделать, это написать запрос, чтобы сгруппировать все строки в одном, где разница во времени с последней записи вхождение менее чем за 30 минут на идентичном IPAddress и Имя пользователя или другими словами выберите/возвращать только последнюю запись для того же IPAddress и Username и удалять все остальные строки до этого.

Желаемый результат только те строки, с стрелкой рядом с ними (изображение ниже):

enter image description here

+2

Каков ваш желаемый результат? – sgeddes

+0

@sgeddes Представьте себе «blob» строк, которые не определены ни одной строкой в ​​блобе, находящейся более чем на 30 минут от каждой другой строки. Он хочет, чтобы все эти «blobs» на IPAddress и Username были сгруппированы по строкам. – Patashu

+0

Проблема в том, что вам нужно будет скопировать время в 30-минутные куски и сгруппировать их по IP и TimeChunk. Вы не можете просто сказать «в течение 30 минут друг от друга», потому что, если записи распространяются более чем на 30 минут, они не будут знать, как их группировать. –

ответ

0

Это должно получить вас там наполовину. Он ищет все записи, которые не имеют другого в течение 30 минут после (или наоборот, ищет записи, которые не имеют еще 30 минут до этого)

Это должно дать вам дату/время окончания каждый «blob» записей.

SELECT m1.IpAddress, m1.DateCreated 
FROM MyLog m1 LEFT OUTER JOIN MyLog m2 
       ON m1.IpAddress = m2.IpAddress AND 
        DATEDIFF(minute, m1.DateCreated, m2.DateCreated) BETWEEN 0 AND 30 
WHERE m2.DateCreated IS NULL 

Это должно дать вам дату/время начала каждого «блоба».

SELECT m1.IpAddress, m1.DateCreated 
FROM MyLog m1 LEFT OUTER JOIN MyLog m2 
       ON m1.IpAddress = m2.IpAddress AND 
        DATEDIFF(minute, m2.DateCreated, m1.DateCreated) BETWEEN 0 AND 30 
WHERE m2.DateCreated IS NULL 
+0

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

+0

не уверен, что я понимаю, Паташу сказал, что вы * не хотите гистограммы и хотите «сфотографировать» их вместе, что и я сделал. –

1

Во-первых, ваше требование может быть истолковано более чем один путь, поэтому позвольте мне стат, что я думаю, что вы хотели ... Я думаю, что вы говорите, сеанс заканчивается, когда данный IP-адрес имеет 30 минут пассивность. Поэтому, если IP-адрес попадает на сайт каждую минуту в течение 2 часов, а затем занимает 30-минутный перерыв, который представляет один сеанс. Предполагая, что это вы ...

Вы можете использовать LEAD и LAG, чтобы помочь вам определить сеансы. Мои тестовые данные состояли из столбца Id, столбца IPAddress и столбца «Создать». Вот код, объяснение следует ...

WITH t1 AS 
(
    SELECT 
     * 
     , DATEDIFF(minute, LAG(Created, 1, 0) OVER (PARTITION BY IPAddress ORDER BY Created), [Created]) AS SinceLastAccess 
    FROM 
     IISLog 
), sessionStarts AS 
(
    SELECT 
     * 
    FROM 
     t1 
    WHERE 
     SinceLastAccess >= 30 
), sessionInfo AS 
(
    SELECT 
     IPAddress 
     , Created AS SessionStart 
     , LEAD(Created, 1, '2025-01-01') OVER (PARTITION BY IPAddress ORDER BY CREATED) AS SessionEnd 
    FROM 
     sessionStarts 
) 

SELECT * FROM sessionInfo 

Первый КТР (t1) выбирает данные, но добавляет столбец SinceLastAccess. Этот новый столбец использует функцию LAG, чтобы посмотреть на значение в предыдущей строке и вычислить, сколько минут прошло. PARTITION BY ограничивает это вычисление на каждый IP-адрес.

Второй CTE (sessionStarts) просто выбирает эти строки из t1, где значение SinceLastAccess больше 30. Это эффективно сообщает нам начало каждой сессии.

И, наконец, CTE `sessionInfo 'основывается на втором. Используя функцию LEAD, мы с нетерпением ждем, где начнется следующий сеанс. Это значение принимается при завершении сеанса текущей строки. В итоге мы получили IP-адрес, начало сеанса и конец сеанса. Теперь, когда у вас есть это, должно быть легко подключиться к исходной таблице и GROUP.

+0

Функции LEAD и LAG, похоже, недоступны в SQL Server 2008 !!! –

+0

Bah! Забыл мой тестовый автомат в 2012 году. Ознакомьтесь с этой ссылкой о стимулировании свинца/запаздывания в 2008 году, возможно, это поможет. http://www.rafael-salas.com/2008/05/t-sql-lead-and-lag-functions.html?m=1 – dazedandconfused

0

Замечательная вещь в Microsoft SQL заключается в том, что у них есть нестандартная опция «select top n ...»; и вот что вы можете использовать здесь:

select * from 

(
select 
id, 
ipAdress, 
created, 
(
select 
top 1 
created 
from tbl as tPrevious 
where tPrevious.ipAdress=t.ipAdress 
and tPrevious.created<t.created 
order by created desc 
) as previousCreated 
from tbl as t 
) as joined 

where 
previousCreated is not null 
and DATEDIFF(min, created,previousCreated) between 0 and 30 
Смежные вопросы