2014-08-29 4 views
0

Q: Mysql Counting the consecutive number rows that match коснулся этого, но хотел бы помочь в его расширении.Mysql Подсчет последних рядов строк подряд, которые соответствуют нескольким идентификаторам

У меня есть несколько пользователей в таблице платежей и необходимости подсчета самых последних неудавшихся платежей, где:

1 = Успех, 2 = Fail

Она должна быть основана на самых последних платежи, а не общий счетчик ! Таким образом, у человека могли быть неудачи, но счет был бы равен нулю, если последний платеж был успешным.

CREATE TABLE Payment 
(`pID` int, `memID` int, `pStatus` int,) 
; 

INSERT INTO Payment 
(`pID`, `memID`, `pStatus) 
VALUES 
(1, 1, 1001), 
(2, 1, 1001), 
(3, 1, 1001), 
(4, 2, 1001), 
(5, 2, 1001), 
(6, 1, 1002), 
(7, 2, 1002), 
(8, 2, 1002), 
(9, 1, 1002), 
(10, 1, 1002), 
(11, 2, 1003), 
(12, 1, 1003), 
(13, 2, 1003), 
(14, 1, 1003), 
(15, 2, 1003), 
(16, 2, 1004), 
(17, 2, 1004), 
(18, 2, 1004), 
(19, 2, 1004), 
(20, 2, 1004); 

Retun должно быть:

memId | failCount 
1001 | 2 
1002 | 0 
1003 | 1 
1004 | 5 
+0

Мы не видим столбцов DATETIME или TIMESTAMP, поэтому мы должны определить, что платеж более «недавний», чем другой платеж, по значению в столбце «pID»; большее значение 'pID 'означает, что платеж более поздний, чем строка с значением' pID', которое ниже? – spencer7593

+0

Итак? Что мешает вам писать такой запрос? Где вы застряли? –

+0

Вы хотите считать '2' в обратном порядке 'pID' до тех пор, пока не будет найдено' 1'? –

ответ

0

Хммм. Мы можем получить максимальный идентификатор последнего , который не прошел платеж, а затем суммировать неудачные платежи с большими идентификаторами. Это в основном делает то, что вы хотите:

select p.memid, count(*) 
from payment p 
where id > coalesce((select max(id) from payment p2 where p2.memid = p.memid and p2.pstatus = 1), 0) 
group by p.memid; 

Но, это не возвращает 0s, так что давайте превратить это в условной агрегации:

select p.memid, 
     sum(id > coalesce((select max(id) from payment p2 where p2.memid = p.memid and p2.pstatus = 1), 0) 
     ) as numfails 
from payment p 
group by p.memid; 

Here является SQL Скрипки.

+0

Спасибо, отлично работает!А условная агрегация также позволяет мне обрабатывать состояние ожидания 3. Изменяя свой p2.pstatus = 1 на p2.pstatus <> 2. Отличная работа. – FLOG51

0

Существует несколько способов получить этот результат. Вот пример одного из этих подходов, вероятно, не самый эффективный, но довольно легко понять, что он делает:

SELECT n.memID 
    , COUNT(r.pStatus) AS failCount 
    FROM (SELECT m.memID 
      FROM Payment m 
      GROUP BY m.memID 
     ) n 
    LEFT 
    JOIN Payment r 
    ON r.memID = n.memID 
    AND r.pStatus = 2 
    AND NOT EXISTS (SELECT 1 
         FROM Payment p 
        WHERE p.memID = r.memID 
         AND p.pStatus = 1 
         AND p.pID > r.pID 
       ) 
GROUP BY n.memID 

Рядный вид n получает нам список всех memID из таблицы платежей; мы могли бы использовать какой-то другой источник, например таблицу, в которой memID является основным ключом, но нам не предоставлена ​​какая-либо информация об этом, поэтому мы создаем отдельный список из таблицы «Оплата».

Далее мы выполняем внешнее соединение с строками в таблице «Оплата», которые имеют статус «сбой». «Трюк», который мы используем, является предикатом НЕ СУЩЕСТВУЮЩИЙ, чтобы проверить, есть ли или нет, более поздняя строка в Платеже, которая имеет статус «Успех». Мы возвращаем строку только в том случае, если не существует более новой строки успеха.

Затем мы выполняем операцию GROUP BY для агрегирования строк, поэтому мы получаем одну строку для каждого memID. И мы получаем счет неудачных платежей, делая агрегат COUNT() в столбце от r, который, как мы знаем, будет не нулевым, если мы найдем совпадение.

Это не единственный способ получить результат, существует несколько других подходов.

Смежные вопросы