Запуск по временным сегментам с TSQL? - PullRequest
1 голос
/ 12 января 2012

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

9fb63b905a004106bd26c80a5caec52b    9   2012-01-12 00:05:56.890
9fb63b905a004106bd26c80a5caec52b    11  2012-01-12 00:05:47.097
9fb63b905a004106bd26c80a5caec52b    10  2012-01-12 00:05:36.713
9fb63b905a004106bd26c80a5caec52b    6   2012-01-12 00:05:26.963
9fb63b905a004106bd26c80a5caec52b    NULL    2012-01-12 00:05:20.500

У меня есть другая таблица, в которой у меня есть некоторые значения триггера.Например, 10 секунд, 30 секунд, 90 секунд со значением триггера, которое я хочу прочитать, когда каждая цель поражена.

После того, как событие записано, у меня есть запрос, который проверяет, есть ли время запускабыло превышено:

SELECT TriggerValue, SUM(p.LastEventTimeSpan)
FROM PageVisitEvents p RIGHT JOIN Segments s ON p.CampaignID = s.CampaignID
WHERE p.VisitorID = '9fb63b905a004106bd26c80a5caec52b'
GROUP BY TriggerValue

Это прекрасно работает, если я хочу запускать только один раз.Однако приведенный выше запрос возвращает следующее (триггерное значение) общее время):

30  357
60  357
90  357

С одним значением выполнение сравнения просто прекрасно, однако мое сравнение теперь показывает только 90, когда это время было превышено, иничего между ними.

Когда встречается каждый триггер, я хотел бы вернуться только для этого триггера.Например, когда время между событиями достигает 35 секунд, возвращайте только триггерное значение в течение 30, а не 10 секунд.

Могу ли я получить некоторые советы о том, как справиться с этим?

Благодаря.

Ответы [ 2 ]

0 голосов
/ 12 января 2012

@ Damien_The_Unbeliever

Я вижу, что вы говорите о дорогих, и я бы хотел избежать большого количества объединений, поэтому я добавил их в представление, выполнил подзапрос на это:

SELECT TOP (1) TriggerValue
FROM dbo.vw_CombinedView
WHERE SegmentID = 2
AND TriggerValue < (
    SELECT SUM(p.LastEventTimeSpan) AS TotalTime
    FROM PageVisitEvents p
        WHERE p.VisitorID = '9fb63b905a004106bd26c80a5caec52b'
    )
ORDER BY TriggerValue DESC

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

Спасибо.

0 голосов
/ 12 января 2012

Я предполагаю, что значения триггера приходят от Segments.Во-первых, давайте отделим суммирование значений в таблице PageVisitEvents от сопоставления с таблицей Segments.Мы могли бы сделать это с помощью подзапроса или CTE, я выбрал CTE (и назвал его SummedEvents).

Затем нам нужно найти соответствующую строку в Segments, которая имеет самый высокий триггерзначение ниже суммы.Мы могли бы сделать это одним из немногих способов, но я предпочитаю делать анти-объединение.Вы можете использовать TOP/ORDER BY, но это работает только тогда, когда требуется ровно один результат.

Итак, у нас есть:

;WITH SummedEvents as (
    SELECT VisitorID,SUM(LastEventTimeSpan) as TotalSpan from PageVisitEvents
    GROUP BY VisitorID
)
SELECT
    TriggerValue,TotalSpan
FROM
    SummedEvents se
        inner join
    Segments s
        on
            se.TotalSpan > s.TriggerValue
        left join
    Segments s_anti
        on
            se.TotalSpan > s_anti.TriggerValue and
            s_anti.TriggerValue > a.TriggerValue
WHERE
    se.VisitorID = '9fb63b905a004106bd26c80a5caec52b' AND
    s_anti.TriggerValue is null

Анти-объединение - это комбинация левого объединения.в s_anti (где мы пытаемся найти более подходящую строку из Segments, чем строка в s) и фильтр предложений WHERE s_anti.TriggerValue is null, который гарантирует, что левое соединение было неудачным.

Вы можете беспокоиться о том, что CTE будет дорогостоящим, и рассчитать сумму для всех значений VisitorID.Это может быть (если SQL Server особенно тупой), но, как правило, он должен определить, что он может фильтровать только по 9fb63b905a004106bd26c80a5caec52b строкам и вычислять только одну строку.Но я сделал это таким образом, потому что форма вышеупомянутого запроса будет более широко использоваться для других запросов.Но если производительность низкая, переместите первое условие условия WHERE в CTE и посмотрите, не улучшится ли это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...