2016-01-24 83 views
1

我有一個名爲wallet的表,它記錄所有錢包事務。假設用戶可以通過4種方式向錢包添加資金,即我有相應的列的credit_src1,credit_src2,credit_src3,credit_src4。此外,用戶可以從他們的賬戶中扣款,所以我有一個相應的列。 每筆交易的信用卡或借記卡都記錄在相應的交易ID表中。用戶只能對事務標識執行一項操作。SQL - 分配/減去多列中的列

我想檢索當用戶從錢包中扣除時每個信用源中剩餘的相應金額。假設從每個來源平均扣除金額。如果量在一列到達0時,它被平等地從剩餘的列中扣除,直到達到那些0

這是源表:

ID src1 src2 src3 src4 debit 
========================================== 
1  10  0  0  0  0 
2  10  0  0  0  0 
3  0  50  0  0  0 
4  0  0  40  0  0 
5  0  0  0  0  30 
6  0  0  0  0  70 

目標表應該是所有來源減去等於借方的累加值從各個來源:

ID src1 src2 src3 src4 debit 
========================================== 
1  10  0  0  0  0 
2  20  0  0  0  0 
3  20  50  0  0  0 
4  20  50  40  0  0 
5  10  40  30  0  30 
6  0  20  10  0  70 

我可以用這個查詢

SELECT 
SUM(src1) OVER (ORDER BY ID), 
SUM(src2) OVER (ORDER BY ID), 
SUM(src3) OVER (ORDER BY ID), 
SUM(src1) OVER (ORDER BY ID) 
FROM wallet 
獲得的各種來源的資金總和

我無法弄清楚如何平均分配所有來源的借項金額。任何形式的幫助將不勝感激。

http://sqlfiddle.com/#!15/893c6/4

+0

的客戶對於這種操縱的,你應該使用存儲過程邏輯(CREATE FUNCTION ),或者使用連接到數據庫的編程語言。 – trincot

+0

我認爲實現這一目標的唯一方法是使用遞歸CTE,而BigQuery不支持。 –

+0

你將如何使用遞歸CTE或程序來做到這一點? – Ayush

回答

2

的BigQuery和BQL是相當強大的,以克服一些意見你的問題中提到的限制!至少在這樣的一些情況下。所以...

下面就是你正在尋找的。 完全BigQuery中利用JS UDF

SELECT id, src1, src2, src3, src4, debit FROM JS(
// input table 
(
    SELECT GROUP_CONCAT(tx) AS txs 
    FROM (
    SELECT CONCAT(STRING(id), '|' , STRING(src1), '|' , 
        STRING(src2), '|' , STRING(src3), '|' , 
        STRING(src4), '|' , STRING(debit) 
      ) AS tx 
    FROM wallet 
    ORDER BY id 
) 
) , 
// input columns 
txs, 
// output schema 
"[ 
{name: 'id', type: 'integer'}, 
{name: 'src1', type: 'integer'}, 
{name: 'src2', type: 'integer'}, 
{name: 'src3', type: 'integer'}, 
{name: 'src4', type: 'integer'}, 
{name: 'debit', type: 'integer'} 
]", 
// function 
"function(r, emit){ 
    var tx_list = r.txs.split(','); 
    var src1_total = 0; 
    var src2_total = 0; 
    var src3_total = 0; 
    var src4_total = 0; 
    var id = 0; 
    var debit = 0; 
    var cut = 0; 

    for (var i = 0; i < tx_list.length; i ++){ 
    var src = tx_list[i].split('|'); 

    id = parseInt(src[0]); 
    src1_total += parseInt(src[1]); 
    src2_total += parseInt(src[2]); 
    src3_total += parseInt(src[3]); 
    src4_total += parseInt(src[4]); 
    debit = parseInt(src[5]); 
    cut = debit; 

    while (cut > 0) { 
     if (src1_total > 0 && cut > 0) {src1_total--; cut--;} 
     if (src2_total > 0 && cut > 0) {src2_total--; cut--;} 
     if (src3_total > 0 && cut > 0) {src3_total--; cut--;} 
     if (src4_total > 0 && cut > 0) {src4_total--; cut--;} 
    } 

    emit({ 
     id: id, src1: src1_total, src2: src2_total, 
     src3: src3_total, src4: src4_total, debit: debit 
    }); 
    } 

}" 
) 

輸出的:

id src1 src2 src3 src4 debit  
1  10  0  0  0  0  
2  20  0  0  0  0  
3  20  50  0  0  0  
4  20  50  40  0  0  
5  10  40  30  0  30  
6  0  10  0  0  70  

請注意:上述方案是不可擴展的不夠。取決於您的表格(錢包)的大小(行數),您遲早會看到它。並且留意biiling層,因爲它隨着行數的增長而變高。

我的建議:在情況下,如果你willhit限制上面提到的 - 你應該在代碼類似於您在本例中的UDF看你的選擇