У меня есть таблица с транзакциями:
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 do (даже если счет 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. Присоединение идет упорядочено по дате. Группировка по идентификатору Мне удалось получить только первый результат объединения, который является следующей транзакцией для той же учетной записи.
Затем по внешнему выбору я отфильтровываю те, у которых есть «А», поскольку это означает, что следующая транзакция фактически была для него отменой. Другими словами, если для той же учетной записи нет следующей транзакции или если следующей транзакцией является '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 |
+----+---------+------+---------------------+--------+--------+----------+
Он связывает каждую транзакцию со следующей по времени для той же учетной записи, а затем отфильтровывает те, которые были отменены ... Успех !!
Как я уже сказал, проблема сейчас в оптимизации. В моих реальных данных много строк (как ожидается, таблица будет содержать транзакции во времени), и для таблицы с ~ 10000 строк я получил положительный результат с этим запросом за 1 мин.44 сек. Я полагаю, что это то же самое с соединениями ... (Для тех, кто знает протокол здесь, что мне делать? Запустите новый вопрос здесь и опубликуйте его как решение этого вопроса? Или просто подождите здесь больше ответов?)