SQL: Как найти лучших клиентов, которые платят 80% дохода? - PullRequest
0 голосов
/ 10 сентября 2018

Допустим, у меня есть таблица TRANSACTIONS:

desc customer_transactions; 
+------------------------------+--------------+------+-----+---------+----------------+
| Field                        | Type         | Null | Key | Default | Extra          |
+------------------------------+--------------+------+-----+---------+----------------+
| id                           | int(11)      | NO   | PRI | NULL    | auto_increment |
| transactionID                | varchar(128) | YES  |     | NULL    |                |
| customerID                   | varchar(128) | YES  |     | NULL    |                |
| amountAuthorized             | DECIMAL(5,2) | YES  |     | NULL    |                |
| createdDatetime              | datetime     | YES  |     | NULL    |                |
+------------------------------+--------------+------+-----+---------+----------------+

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

Мне нужно найти главных клиентов, которые отвечают за 80% всех доходов (за период времени).Бизнес SAAS очень неравномерен, потому что некоторые клиенты платят 10 / месяц, другие могут платить тысячами в месяц.

Я добавлю фильтр "период времени" позже, просто нужна помощь с агрегацией.

Я хочу создать отчет, в котором я выбираю только тех клиентов, которые получили 80% дохода в этом формате:

+------------+-------+
| customerID | Total | 
+------------+-------+

Не уверен, почему этот вопрос был отложен.Мне просто нужна помощь в написании запроса и не хватает опыта работы с SQL.По сути, в заголовке вопроса указывается, что здесь необходимо:

Мне нужно перечислить клиентов и их соответствующие итоги, однако нужно выбрать только тех клиентов, которые составляют 80% от общего дохода.Отчет должен агрегировать итоговые данные по каждому клиенту.

Использование MariaDB версии 10.3.9

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Это та вещь, для которой вам нужно использовать оконные функции.

WITH 
    -- define some sample data, 
    -- where the sum total of amountAuthorized is 10,000
    customer_transactions(  `id`, transactionID, customerID, 
                            amountAuthorized, createdDatetime) AS
    (
                    SELECT 1, 1, 1, 5000, '2018-08-01'
        UNION ALL   SELECT 2, 2, 2, 2000, '2018-08-01'
        UNION ALL   SELECT 3, 3, 3, 1000, '2018-08-01'
        UNION ALL   SELECT 4, 4, 4, 1000, '2018-08-01'
        UNION ALL   SELECT 5, 5, 5, 1000, '2018-08-01'
    )
    -- a query that gives us the running total, sorted to give us the biggest customers first.
    -- note that the additional sorts affect what customers might be returned.
    ,running_totals AS
    (
        SELECT *, SUM(amountAuthorized) OVER (ORDER BY amountAuthorized DESC, createdDatetime DESC, `id`)  AS runningTotal
        FROM customer_transactions
    )
SELECT *
FROM running_totals
WHERE runningTotal <= ( SELECT 0.8 * SUM(amountAuthorized) 
                        FROM customer_transactions)

Обратите внимание, что это учитывает (без каламбура) все данные в таблице. Если вы хотите посмотреть только определенный период времени, вы можете создать промежуточный CTE, который отфильтровывает нужные вам даты.

0 голосов
/ 03 октября 2018

Вы обнаружите, что на удивительно близкие 20% клиентов приходится 80%. См. правило 80/20 .

Но, если вы не хотите идти в этом направлении, у вас есть 2 варианта:

  • Переключиться на MySQL 8.0 или MariaDB 10.1, чтобы использовать «оконные» функции; или
  • Используйте @variables для получения промежуточного итога, затем (во внешнем запросе) возьмите нужные строки.

Поскольку вы используете MariaDB 10.3.9, кажется, что подходить к работе с окнами. Но сначала вам нужен отдельный запрос (или производная таблица), который вычисляет общий доход, чтобы вы могли получить его на 80%.

Предложить

 SELECT @revenue80 := 0.8 * SUM(amountAuthorized) 
     FROM customer_transactions

Затем используйте @revenue80 внутри WHERE, который предлагает Зак.

Я вижу, что каждая сумма может быть не более 999.99. В самом деле? Это кафе?

0 голосов
/ 10 сентября 2018

Используйте следующее:

SELECT 
  ct1.customerID, 
  SUM(ct1.amountAuthorized) as Total, 
  100 * (SUM(ct1.amountAuthorized) / ct3.total_revenue) as percent_revenue 
FROM 
  customer_transactions ct1
CROSS JOIN (SELECT SUM(amountAuthorized) AS total_revenue 
            FROM customer_transactions ct2) AS ct3 
GROUP BY 
  ct1.customerID 
HAVING percent_revenue >= 80
...