2016-07-08 67 views
0

我需要幫助解決MySQL問題。我有兩張桌子,一張叫做subscription,另一張叫做payment。每個訂閱都有多個付款。有些付款未啓動(0),有些付款失敗(1),有些付款成功(2)。MySQL - 是否可以使用正則表達式對行進行計數?

每個訂閱都可以產生多次付款嘗試,直到獲得成功。例如:

  • 第一次嘗試網絡連接問題,並得到status = 0
  • 第二次嘗試到達支付A​​PI,但信用卡數據錯誤,或沒有足夠的資金,所以它得到status = 1
  • 第三次嘗試是成功的連帶status = 2

前兩個可以比兩個以上,事實上,它可以是這樣的:

0, 1, 0, 0, 1, 1, 1, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 2, 0, 1, 2, 1, 0, 2, 0, 2, 1, 2, 2

所以每次認購有多個付款序列(每月或經常,沒有必要日期相關的),可以通過自己的地位確定與此正則表達式[0|1]*2,得到的東西,如:

0, 1, 0, 0, 1, 1, 1, 1, 2, // 9 
0, 0, 1, 2,     // 4 
1, 0, 1, 2,     // 4 
2,       // 1 
2,       // 1 
0, 1, 2,      // 3 
1, 0, 2,      // 3 
0, 2,      // 2 
1, 2,      // 2 
2       // 1 

但是,當然,由於有多個訂閱,付款行在數據庫中混合,唯一連接它們的是subscription_id

我需要得到的是從第一次嘗試,第二次嘗試,第三次,...第10次嘗試,10次嘗試中獲得成功支付的訂閱數量。

在上面的例子應該是:

attempts count 
9   1 
4   2 
3   2 
2   2 
1   3 

這可能嗎?

測試數據

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 
SET time_zone = "+00:00"; 

CREATE TABLE IF NOT EXISTS `payment` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`subscription_id` int(11) DEFAULT NULL, 
`status` smallint(6) NOT NULL, 
PRIMARY KEY (`id`), 
KEY `IDX_6D28840D9A1887DC` (`subscription_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPRESSED AUTO_INCREMENT=36 ; 

INSERT INTO `payment` (`id`, `subscription_id`, `status`) VALUES 
(1, 1, 1),(2, 1, 2),(3, 1, 2),(4, 2, 2),(5, 3, 2),(6, 4, 2),(7, 5, 2), 
(8, 6, 1),(9, 6, 2),(10, 7, 2),(11, 7, 2),(12, 8, 0),(13, 8, 1),(14, 8, 2), 
(15, 8, 2),(16, 9, 1),(17, 9, 2),(18, 9, 2),(19, 9, 1),(20, 9, 2),(21, 10, 0), 
(22, 10, 1),(23, 10, 1),(24, 10, 1),(25, 10, 1),(26, 11, 0),(27, 11, 0),(28, 11, 1), 
(29, 11, 1),(30, 11, 1),(31, 8, 0),(32, 8, 1),(33, 8, 2),(34, 10, 1),(35, 10, 2); 

CREATE TABLE IF NOT EXISTS `subscription` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`status` smallint(6) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPRESSED AUTO_INCREMENT=12 ; 

INSERT INTO `subscription` (`id`, `status`) VALUES 
(1, 1),(2, 1),(3, 1),(4, 1),(5, 1),(6, 1),(7, 1), 
(8, 1),(9, 1),(10, 0),(11, 0); 

ALTER TABLE `payment` 
ADD CONSTRAINT `sub_id` FOREIGN KEY (`subscription_id`) REFERENCES `subscription` (`id`); 

注:測試數據不是類似於上面的例子。對於測試數據的結果應該是這樣的:

subscription_id cntAttempts  [attempts counted] 
1     2    1, 2, 
1     1    2, 
2     1    2, 
3     1    2, 
4     1    2, 
5     1    2, 
6     2    1, 2, 
7     1    2, 
7     1    2, 
8     3    0, 1, 2, 
8     1    2, 
9     2    1, 2, 
9     1    2, 
9     2    1, 2, 
10     7    0, 1, 1, 1, 1, 1, 2 
11     5    0, 0, 1, 1, 1, 
8     3    0, 1, 2, 

對於subscription_id = 10最後兩筆款項分別後118那些在最後插入。

預期的最終結果:

paymentAttemptsCount count 
1      9 
2      5 
3      1 
4      0 
5      1 
6      0 
7      1 
8      0 
9      0 
10      0 

注:認購與id = 11沒有成功付款。

+0

對不起!我首先寫了這個例子,然後我創建了測試數據庫。我已經用測試數據預期的結果更新了這個問題。謝謝! –

+0

如何計算每次訂閱的付款順序,例如,如果您對subscription_id = 1有seq1:0,2和seq2:1,2,您怎麼知道您有2次付款,每次付款2次,而不是2次付款分別有3次和1次嘗試。在分貝你會hava 0,1,2,2 –

+0

您的問題可能類似於http://stackoverflow.com/questions/9231447/how-to-count-the-number-of-groups-returned-by -a-group-by –

回答

0

如上所述,您實際上應該爲paymentid/invoicenumber(這將是發票表的外鍵)添加一列,以將多次付款嘗試歸爲一組 - 因爲它們屬於一起,您的數據模型應代表該邏輯。你的問題似乎更復雜,因爲你錯過了這些數據。

您可以在運行時計算該ID(至少如果您是按順序添加它們的,並且不會混合支付相同的subscription_id,例如因爲發票可能在下個月仍然打開,而您現在嘗試同時開具發票) 。對於第一個查詢,您可以使用

select subscription_id, 
     count(*) as cntAttempts, 
     group_concat(status order by id) as attempts_counted 
from 
    (SELECT id, subscription_id, status, 
     @pid := CASE WHEN @last_status = 2 or subscription_id <> @last_id 
         THEN @pid + 1 else @pid END as pid, 
     @last_id := subscription_id, 
     @last_status := status 
    from (select @last_id := 0, @pid := 0, @last_status := 0) init, payment 
    order by subscription_id, id 
) as payment_grpd 
group by pid, subscription_id; 

你的第二個查詢將需要組這一結果再次,e.g和看起來像

select cntAttempts, 
     count(*) as count 
from 
    (select pid, 
      count(*) as cntAttempts 
    from 
    (SELECT id, subscription_id, status, 
      @pid := CASE WHEN @last_status = 2 or subscription_id <> @last_id 
         THEN @pid + 1 else @pid END as pid, 
      @last_id := subscription_id, 
      @last_status := status 
     from (select @last_id := 0, @pid := 0, @last_status := 0) init, payment 
     order by subscription_id, id 
    ) as payment_grpd 
    group by pid, subscription_id 
) as subcounts 
group by cntAttempts; 

子查詢payment_grpd將重新計算你的ID。如果您添加缺少的關係,你的第一個查詢只會像

select subscription_id, 
     count(*) as cntAttempts, 
     group_concat(status order by id) as attempts_counted 
from payment 
group by pid, subscription_id; 

同樣地,對於第二個。要正常化,可能必須將subscription_id移至參考表。

+0

添加了一個'NULL'的invoice_no'列,用於序列的最終付款不成功,現在選擇數據很簡單!感謝您的支持。 –

相關問題