Mysql - Имитация лага с несколькими предыдущими рядами (не только один) - PullRequest
0 голосов
/ 04 февраля 2019

После нескольких часов борьбы с этим, имитации задержки (я нахожусь на MySQL 5.6 без возможности обновления) и обнаружении пары функциональных проблем, я прихожу сюда за небольшой помощью, теперь я полностью потерян здесь.

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

Образец получен по:

SELECT 
purchaseId
,userId
,purchaseDate 
FROM tempPurchases
WHERE userId > 69
ORDER BY userId, purchaseDate;


+------------+--------+--------------+
| purchaseId | userId | purchaseDate |
+------------+--------+--------------+
|       2074 |     70 | 2018-11-12   |
|       2072 |     70 | 2018-11-30   |
|       2108 |     71 | 2018-01-23   |
|       2114 |     71 | 2018-02-27   |
|       2130 |     71 | 2018-03-07   |
|       2115 |     71 | 2018-04-17   |
|       2105 |     71 | 2018-11-12   |
|       2112 |     71 | 2018-11-30   |
|       2145 |     72 | 2018-01-21   |
|       2141 |     72 | 2018-01-23   |
|       2136 |     72 | 2018-02-01   |
|       2148 |     72 | 2018-03-02   |
|       2158 |     72 | 2018-06-06   |
|       2137 |     72 | 2018-07-04   |
|       2139 |     72 | 2018-07-11   |
|       2153 |     72 | 2018-10-18   |
|       2135 |     72 | 2018-10-25   |
|       2157 |     72 | 2018-11-12   |
|       2147 |     72 | 2018-12-30   |
|       2184 |     73 | 2018-02-21   |
|       2166 |     73 | 2018-03-14   |
|       2176 |     73 | 2018-05-12   |
|       2186 |     73 | 2018-07-09   |
|       2173 |     73 | 2018-08-25   |
|       2162 |     73 | 2018-11-12   |
|       2165 |     73 | 2018-11-30   |
+------------+--------+--------------+

Спецификация заключается в том, чтобы сделать «бонус» при покупке за 30 дней (я использовал TIMESTAMPDIFF(DAYS) и лаг для расчета разницы в днях между датой и предыдущей датой. Проблема здесь в том, что бонус также сравнивается с несколькими предыдущимистроки, а не только строка выше. (Логика для столбца A)

Например, в следующем примере для идентификатора пользователя 72 идентификатор покупки 2136 совпадает с 2141, но также с 2145, и, конечно, это переменная, какчеловек, совершивший 10 покупок сегодня и 20 прошлых дней.

Итак, желаемый результат:

+------------+--------+--------------+-----------+------------+--------------------------+
| purchaseId | userId | purchaseDate | days diff | A (streak) | B (streak without reset) |
+------------+--------+--------------+-----------+------------+--------------------------+
|       2074 |     70 | 2018-11-12   |         0 |          0 |                        0 |
|       2072 |     70 | 2018-11-30   |        18 |          1 |                        1 |
|       2108 |     71 | 2018-01-23   |         0 |          0 |                        0 |
|       2114 |     71 | 2018-02-27   |        35 |          0 |                        0 |
|       2130 |     71 | 2018-03-07   |         8 |          1 |                        1 |
|       2115 |     71 | 2018-04-17   |        41 |          0 |                        0 |
|       2105 |     71 | 2018-11-12   |       209 |          0 |                        0 |
|       2112 |     71 | 2018-11-30   |        18 |          1 |                        1 |
|       2145 |     72 | 2018-01-21   |         0 |          0 |                        0 |
|       2141 |     72 | 2018-01-23   |         2 |          1 |                        1 |
|       2136 |     72 | 2018-02-01   |         9 |          2 |                        2 |
|       2148 |     72 | 2018-03-02   |        29 |          1 |                        3 |
|       2158 |     72 | 2018-06-06   |        96 |          0 |                        0 |
|       2137 |     72 | 2018-07-04   |        28 |          1 |                        1 |
|       2139 |     72 | 2018-07-11   |         7 |          1 |                        2 |
|       2153 |     72 | 2018-10-18   |        99 |          0 |                        0 |
|       2135 |     72 | 2018-10-25   |         7 |          1 |                        1 |
|       2157 |     72 | 2018-11-12   |        18 |          2 |                        2 |
|       2147 |     72 | 2018-12-30   |        48 |          0 |                        0 |
|       2184 |     73 | 2018-02-21   |         0 |          0 |                        0 |
|       2166 |     73 | 2018-03-14   |        21 |          1 |                        1 |
|       2176 |     73 | 2018-05-12   |        59 |          0 |                        0 |
|       2186 |     73 | 2018-07-09   |        58 |          0 |                        0 |
|       2173 |     73 | 2018-08-25   |        47 |          0 |                        0 |
|       2162 |     73 | 2018-11-12   |        79 |          0 |                        0 |
|       2165 |     73 | 2018-11-30   |        18 |          1 |                        1 |
+------------+--------+--------------+-----------+------------+--------------------------+

Полностью потерян с одновременным объединением / левым соединением и запаздываниемЛюбые советы, комментарии или ответы будут учтены.Пожалуйста, не сомневайтесь в комментариях или спрашивайте что-либо.

ВОПРОС: Как я могу получить этот расчет для серии, учитывающей "отставание" нескольких строк выше?Мой настоящий подход заключается в использовании курсоров, но в данный момент они не работают.

ОБНОВЛЕНИЕ:

Ожидаемый результат - получение "бонусной полосы" с учетом вышеприведенных строк для одного и того же идентификатора пользователя.Например:

userId 72 совершает покупку (покупка 1) на 01 / янв (значение первой строки равно 0).Затем снова (покупка 2) на 10 / Янв, так что менее чем за 30 дней: 1 балл (10 дней).Снова в 15/01 (покупка 3), поэтому 1 балл за разницу между покупкой 2 (5 дней) и еще 1 балл за покупку 1 (15 дней).Всего бонусов: 3 (0 + 1 + (1 + 1))

1 Ответ

0 голосов
/ 04 февраля 2019

Я полагаю, что все так просто, подзапрос внутри select подсчитывает количество покупок за последние 30 дней:

SELECT t.*, (
    SELECT COUNT(*)
    FROM t AS x
    WHERE userId = t.userId 
    AND purchaseDate <  t.purchaseDate
    AND purchaseDate >= t.purchaseDate - INTERVAL 30 DAY
) AS purchases_within_30days
FROM t
...