Допустим, у меня есть следующие транзакционной данные:MySQL: поиск групп записей в течение определенного периода времени
+--------------------------------------------------+
| CustomerID | TransactionID | TransactionDate |
+--------------------------------------------------+
| 1 | 1 | 2015-01-22 15:09:43 |
| 1 | 2 | 2015-01-22 16:58:13 |
| 1 | 3 | 2015-01-23 07:05:53 |
| 2 | 4 | 2015-02-02 21:12:28 |
| 2 | 5 | 2015-02-02 22:01:59 |
| 3 | 6 | 2015-02-03 19:50:47 |
| 2 | 7 | 2015-02-04 16:12:08 |
| 4 | 8 | 2015-02-05 17:13:29 |
+--------------------------------------------------+
TransactionDate, кстати, хранится в виде метки времени UNIX, а не строковое представление даты. Я просто преобразовал его, чтобы было легче читать здесь.
Я пытаюсь создать запрос, который скажет мне, какие клиенты (по ID) купили 3 или более раз в течение 24-часового окна. В этом (по общему признанию, базовом) примере единственным клиентом, который соответствует этим критериям, является №1, поскольку эти три транзакции произошли в течение 24-часового периода. Клиент № 2 не будет, потому что в течение 24 часов произошло всего две транзакции; третий был за пределами 24-часового окна от первого. Все, о чем я забочусь, это идентификатор клиента; Мне не нужно знать, какие транзакции были задействованы или фактическая дата транзакции. В настоящее время я делаю это с помощью кода - выполнить запрос, который возвращает приведенную выше таблицу в массив PHP, преобразование результатов с помощью кода, как это:
foreach ($results as $result)
$data[$result['CustomerID']][] = array(
'TransactionID' => $result['TransactionID'],
'TransactionDate' => $result['TransactionDate']
);
... который дает мне массив, как это ...
$data = array(
'1' => array(
array(
'TransactionID' => '1',
'TransactionDate' => '2015-01-22 15:09:43'
),
array(
'TransactionID' => '2',
'TransactionDate' => '2015-01-22 16:58:13'
),
array(
'TransactionID' => '3',
'TransactionDate' => '2015-01-23 07:05:53'
),
),
'2' => array(
array(
'TransactionID' => '4',
'TransactionDate' => '2015-02-02 21:12:28'
),
array(
'TransactionID' => '5',
'TransactionDate' => '2015-02-02 22:01:59'
),
array(
'TransactionID' => '7',
'TransactionDate' => '2015-02-04 16:12:08'
),
),
// etc.
)
... и затем пройти через каждый клиент и посмотреть, если третья запись в течение 24 часов после первой записи, если четвёртая запись в течение 24 часов после второй записи и т.д., в зависимости от того, как в течение этого периода для этого клиента имеется много записей о покупке. Если в любой момент я нахожу три записи в течение 24-часового окна, я отмечаю идентификатор клиента и перехожу к следующему (мне все равно, сколько 24-часовых блоков из 3+ транзакций я нахожу, именно так я нашел хотя бы один).
Если бы это было так просто, как 8 записей транзакций, я был бы счастлив оставить это как некоторый процедурный код, как я изложил здесь; но когда я перетаскиваю 92 000 записей из базы данных в PHP для обработки (и каждая запись больше похожа на 70 полей, а не на 3), я начинаю сталкиваться с серьезными проблемами памяти и тайм-аута. Я знаю, потому что раньше я работал с большими наборами данных (в миллионах строк), что любой сервер базы данных, заслуживающий своей соли, может справиться с такими вычислениями намного быстрее, чем PHP, работающий как модуль под Apache. Я не знаю, как я могу рассчитать время между записями непосредственно в среде запросов. Возможна ли такая обработка в MySQL?
Вы можете использовать ['TIMEDIFF()'] (http://www.w3resource.com/mysql/date-and-time-functions/mysql-timediff-function.php) в mysql. –
Я пытаюсь не обрабатывать 90 000 записей в моей хранимой процедуре. В идеале я хотел бы, чтобы результат 'timediff()' был вычисляемым столбцом в запросе, который затем можно выбрать с помощью предложения 'HAVING'. Это скорее вопрос создания запроса, в котором строка n вычисляется на основе содержимого строки n-1. – mounty