Нахождение, когда запросы удовлетворены или превышены клиентом по месяцам
У меня есть таблица, в которой есть клиенты, и я хочу узнать, в каком месяце клиент встречал или превысил определенное количество запросов.
В таблице customer_id есть отметка времени каждого запроса.
То, что я ищу, это месяц (или день), когда клиент встретил или превысил 10000 запросов. Я пытался получить промежуточный итог на месте, но это просто не работает для меня. Я оставил это в коде на случай, если кто-то знает, как я могу это сделать.
У меня есть следующее:
SELECT
customer_id
, DATE_TRUNC(CAST(TIMESTAMP_MILLIS(created_timestamp) AS DATE), MONTH) as cMonth
, COUNT(created_timestamp) as searchCount
-- , SUM(COUNT (DISTINCT(created_timestamp))) OVER (ROWS UNBOUNDED PRECEDING) as RunningTotal2
FROM customer_requests.history.all
GROUP BY distributor_id, cMonth
ORDER BY 2 ASC, 1 DESC;
Представление, за которым я следую, выглядит примерно так.
customer requests cMonth totalRequests
cust1 6000 2017-10-01 6000
cust1 4001 2017-11-01 10001
cust2 4000 2017-10-01 4000
cust2 4000 2017-11-01 8000
cust2 4000 2017-12-01 12000
cust2 3000 2017-12-01 3000
cust2 3000 2017-12-01 6000
cust2 3000 2017-12-01 9000
cust2 3000 2017-12-01 12000
3 ответа
Это мое решение.
SELECT
customerid
,SUM(requests) sumDay
,created_timestamp
FROM yourTable
GROUP BY
customerid,
created_timestamp
HAVING SUM(requests) >= 10000;
Это довольно просто. Вы просто группируете в соответствии с вашими потребностями, суммируете запросы и выбираете строки, которые соответствуют вашему предложению HAVING. Вы можете попробовать запрос здесь.
Предполагая SQL Server, попробуйте это (отрегулировав обрезку сверху, чтобы получить количество транзакций, которое вам нужно; сейчас он ищет тысячную транзакцию для каждого клиента).
Обратите внимание, что это не вернет клиентов, которые не превысили ваш предел, и предполагает, что каждая транзакция имеет уникальную дату (или ей присваивается последовательный идентификационный номер для разрыва связей, если в дате могут быть связи).
DECLARE @cutoff INT = 1000;
WITH CTE
AS (SELECT customer_id,
transaction_ID,
transaction_date,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY transaction_date, transaction_ID) AS RN,
COUNT(transaction_ID) OVER (PARTITION BY customer_id) AS TotalTransactions
FROM #test)
SELECT DISTINCT
customer_id,
transaction_date as CutoffTransactionDate,
TotalTransactions
FROM CTE
WHERE RN = @cutoff;
Как это устроено:
row_number
присваивает уникальный последовательный идентификатор каждой из транзакций клиента в том порядке, в котором они были сделаны. count
говорит вам общее количество транзакций, совершенных человеком (при условии, что на каждую транзакцию снова будет приходиться одна запись - в противном случае вам придется рассчитывать это отдельно, distinct
не будет работать с partition
).
Потом второй select
возвращает 1000-ю (или сколько бы вы ни указали) строку для каждого клиента и его дату, а также итоговую сумму для этого клиента.
Если вам нужна накопительная сумма, вы можете использовать оконные функции. В стандартном SQL это выглядит так:
SELECT customer_id,
DATE_TRUNC(CAST(TIMESTAMP_MILLIS(created_timestamp) AS DATE), MONTH) as cMonth
COUNT(*) as searchCount,
SUM(COUNT(*)) OVER (ORDER BY MIN(created_timestamp) as runningtotal
FROM customer_requests.history.all
GROUP BY distributor_id, cMonth
ORDER BY 2 ASC, 1 DESC;