Нахождение максимального количества строк, созданных за час?

У меня есть таблица для хранения отзывов о товаре, как это:

Id -int
ProductId -int
Timestamp -datetime
Comments -text

Есть ли простой способ подсчитать и определить частоту отзывов продукта за 60 минут? то есть. Widget1 максимальное количество отзывов / час 55.

работа с sql05.

5 ответов

Я не знаю простого способа вычисления этой метрики, но, надеюсь, это поможет. Без какого-либо курсора SQL я бы сгенерировал таблицу SQL возможных интервалов с отметками времени начала и конца (2009-09-02T00:00 до 2009-09-02T00:59, 2009-09-02T00:01 до 2009-09-02T01:00 и т. Д.), А затем перекрестное соединение с использованием LINQ to SQL:

var rates = from r in db.Reviews
            from i in db.Intervals
            where i.Begin <= r.Timestamp && r.Timestamp <= i.End
            group r by i.Begin into reviews
            select reviews.Count();
var maxRate = rates.Max();

Я не пробовал код, но он должен помочь вам начать. Вы можете улучшить производительность, ограничив время проверки (последние 7 дней, 30 дней и т. Д.) Или сгенерировав меньше интервалов (возможно, начиная с четверть часа).

Другой вариант - использовать функции SQL DATEPART, например:

SELECT
    DAY(TimeStamp), MONTH(TimeStamp), YEAR(TimeStamp),
    DATEPART(HOUR, TimeStamp),
    COUNT(*)
FROM    
    dbo.Products
GROUP BY
    DAY(TimeStamp), MONTH(TimeStamp), YEAR(TimeStamp),
    DATEPART(HOUR, TimeStamp)
ORDER BY
    COUNT(*) DESC

Это дает вам не только максимальное количество просмотров за определенный час, но и все они, отсортированные по частоте. Имейте в виду: кроме решения RexM, это основано на "часовой" части вашей "метки времени" - так что, если у вас есть довольно много просмотров в 7:59 и еще один взрыв в 8:01, в моем решении, эти не могут быть показаны вместе (так как один час =7, а другой час =8).

Если вам нужен подход "любой 60-минутный интервал", используйте основную идею RexM (DATEDIFF с минутами <= 60).

Марк

Если вместо этого вы хотите "какой продукт получил наибольшее количество отзывов в 60-минутном блоке между dateX и dateY", то это немного сложнее.

Один из способов думать об этом - "для каждого отзыва за тот же период времени, сколько других обзоров для того же идентификатора продукта существует в следующие 60 минут". Если у вас есть такая логика, запрос становится более понятным:

SELECT TOP 1
    PR.ProductID,
    -- start of 60 minute block
    PR.Timestamp,
    ReviewCount = (
        SELECT COUNT(*)
        FROM ProductReviews PR1
        -- from parent time
        WHERE PR1.Timestamp >= PR.Timestamp
        -- until 60 mins later
        AND PR1.Timestamp <= DATEADD( minute, 60, PR.Timestamp )
        -- that matches ProductID
        AND PR1.ProductID = PR.ProductID
    )
FROM ProductReviews PR
-- in the last 24 hours
WHERE PR.Timestamp > ( GETDATE() - 1 )
ORDER BY ReviewCount DESC

Как это?

Если вы работаете с установленным 60-минутным блоком времени (например, последние 60 минут с этого момента), то это достаточно просто:

SELECT TOP 1
    PR.ProductID,
    COUNT(*)
FROM ProductReviews PR
WHERE PR.Timestamp BETWEEN DATEADD( minute, -60, GETDATE() ) AND GETDATE()
GROUP BY PR.ProductID
ORDER BY COUNT(*) DESC

Если вы хотите его в течение любого 60-минутного интервала, тогда это становится более сложным!

Если вы были довольны фиксированными часами для своих окон, я мог бы подумать о том, чтобы сделать это немного умнее, используя триггер. Триггер вставляет / обновляет в таблицу 'log' и просто различает вставку или обновление в зависимости от текущего времени.

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

Другие вопросы по тегам