У меня есть таблица с транзакциями:
Transactions
------------
id | account | type | date_time | amount
----------------------------------------------------
1 | 001 | 'R' | '2012-01-01 10:01:00' | 1000
2 | 003 | 'R' | '2012-01-02 12:53:10' | 1500
3 | 003 | 'A' | '2012-01-03 13:10:01' | -1500
4 | 002 | 'R' | '2012-01-03 17:56:00' | 2000
5 | 001 | 'R' | '2012-01-04 12:30:01' | 1000
6 | 002 | 'A' | '2012-01-04 13:23:01' | -2000
7 | 003 | 'R' | '2012-01-04 15:13:10' | 3000
8 | 003 | 'R' | '2012-01-05 12:12:00' | 1250
9 | 003 | 'A' | '2012-01-06 17:24:01' | -1250
и я хочу выбрать все определенного типа («R»), но не те, которые сразу (в порядке поля date_time) имеют другую транзакцию другого типа («A») для той же учетной записи...
Таким образом, запрос должен выдать следующие строки, учитывая предыдущий пример:
id | account |type | date | amount
----------------------------------------------------
1 | 001 | 'R' | '2012-01-01 10:01:00' | 1000
5 | 001 | 'R' | '2012-01-04 12:30:01' | 1000
7 | 003 | 'R' | '2012-01-04 15:13:10' | 3000
(Как видите, строка 2 не отображается, потому что строка 3 «отменяет» ее... также строка 4 «отменяется» строкой 6'; появляется строка 7 (хотя учетная запись 003 принадлежит отмененной строке № 2). , на этот раз в строке 7 она не отменяется ни одной строкой «А»); И строка 8 не появится (это тоже для 003 счета, так как теперь эта отменяется на 9, что тоже не отменяет 7, просто предыдущий раз: 8...
Я пробовал соединения, подзапросы в предложениях Where, но я действительно не уверен, как мне сделать свой запрос...
Что я пробовал:
Попытка присоединяется:
SELECT trans.type as type,
trans.amount as amount,
trans.date_time as dt,
trans.account as acct,
FROM Transactions trans
INNER JOIN ( SELECT t.type AS type, t.acct AS acct, t.date_time AS date_time
FROM Transactions t
WHERE t.date_time > trans.date_time
ORDER BY t.date_time DESC
) AS nextTrans
ON nextTrans.acct = trans.acct
WHERE trans.type IN ('R')
AND nextTrans.type NOT IN ('A')
ORDER BY DATE(trans.date_time) ASC
Это вызывает ошибку, так как я не могу ввести внешние значения для JOIN в MySQL.
Попытка подзапроса, где:
SELECT trans.type as type,
trans.amount as amount,
trans.date_time as dt,
trans.account as acct,
FROM Transactions trans
WHERE trans.type IN ('R')
AND trans.datetime <
( SELECT t.date_time AS date_time
FROM Transactions t
WHERE t.account = trans.account
ORDER BY t.date_time DESC
) AS nextTrans
ON nextTrans.acct = trans.acct
ORDER BY DATE(trans.date_time) ASC
Это неправильно, я могу ввести внешние значения в WHERE в MySQL, но мне не удается найти способ правильно фильтровать то, что мне нужно...
ВАЖНОЕ РЕДАКТИРОВАТЬ:
Мне удалось добиться решения, но теперь оно нуждается в серьезной оптимизации. Вот:
SELECT *
FROM (SELECT t1.*, tFlagged.id AS cancId, tFlagged.type AS cancFlag
FROM transactions t1
LEFT JOIN (SELECT t2.*
FROM transactions t2
ORDER BY t2.date_time ASC ) tFlagged
ON (t1.account=tFlagged.account
AND
t1.date_time < tFlagged.date_time)
WHERE t1.type = 'R'
GROUP BY t1.id) tCanc
WHERE tCanc.cancFlag IS NULL
OR tCanc.cancFlag <> 'A'
Я присоединился к таблице сам с собой, просто учитывая ту же учетную запись и отличное время date_time. Присоединение идет по дате_времени. Группировка по идентификатору Мне удалось получить только первый результат соединения, который оказывается следующей транзакцией для той же учетной записи.
Затем при внешнем выборе я отфильтровываю те, у которых есть «A», поскольку это означает, что следующая транзакция была фактически отменой для нее. Другими словами, если следующей транзакции для того же аккаунта нет или если следующая транзакция является «R», то она не отменяется и должна отображаться в результате...
Я получил это:
+----+---------+------+---------------------+--------+--------+----------+
| id | account | type | date_time | amount | cancId | cancFlag |
+----+---------+------+---------------------+--------+--------+----------+
| 1 | 001 | R | 2012-01-01 10:01:00 | 1000 | 5 | R |
| 5 | 001 | R | 2012-01-04 12:30:01 | 1000 | NULL | NULL |
| 7 | 003 | R | 2012-01-04 15:13:10 | 3000 | 8 | R |
+----+---------+------+---------------------+--------+--------+----------+
Он связывает каждую транзакцию со следующей по времени для той же учетной записи, а затем отфильтровывает те, которые были отменены... Успех!!
Как я уже сказал, проблема сейчас в оптимизации. В моих реальных данных много строк (как ожидается, таблица, содержащая транзакции во времени), и для таблицы из ~ 10 000 строк прямо сейчас я получил положительный результат с этим запросом за 1 минуту 44 секунды. Я полагаю, что дело в соединениях... (Для тех, кто знает протокол здесь, что мне делать? Запустить новый вопрос здесь и опубликовать его как решение этого? Или просто дождаться дополнительных ответов здесь?)