SQL - Distribute/subtract 多列中的一列
SQL - Distribute/subtract a column from multiple columns
我有一个名为 wallet
的 table,它记录所有钱包交易。假设用户可以通过 4 种方式将钱添加到钱包中,即 credit_src1,credit_src2,credit_src3,credit_src4
我有各自的列。另外,用户可以从他们的账户中扣款,所以我有一个对应的列。
每笔贷记或借记交易都使用相应的交易 ID 记录在 table 中。一个用户只能对一个交易id进行一次操作。
当用户从钱包中扣款时,我想检索每个信用来源中剩余的相应金额。假设从每个来源中平均扣除该金额。如果其中一列的amount达到0,则从剩余的列中平均扣除,直到达到0。
这是来源table:
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
目的地 table 应该是所有来源的累计总和减去每个来源的相等借方:
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
我不知道如何在所有来源之间平均分配借记金额。任何形式的帮助将不胜感激。
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
请注意:以上解决方案的可扩展性不够。取决于您 table(钱包)的大小(行数),您迟早会看到它。并注意 biiling 层,因为它会随着行数的增加而变高。
我的建议:如果您遇到上述限制 - 您应该在您选择的客户端上编写类似于您在本例的 udf 中看到的逻辑代码
我有一个名为 wallet
的 table,它记录所有钱包交易。假设用户可以通过 4 种方式将钱添加到钱包中,即 credit_src1,credit_src2,credit_src3,credit_src4
我有各自的列。另外,用户可以从他们的账户中扣款,所以我有一个对应的列。
每笔贷记或借记交易都使用相应的交易 ID 记录在 table 中。一个用户只能对一个交易id进行一次操作。
当用户从钱包中扣款时,我想检索每个信用来源中剩余的相应金额。假设从每个来源中平均扣除该金额。如果其中一列的amount达到0,则从剩余的列中平均扣除,直到达到0。
这是来源table:
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
目的地 table 应该是所有来源的累计总和减去每个来源的相等借方:
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
我不知道如何在所有来源之间平均分配借记金额。任何形式的帮助将不胜感激。
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
请注意:以上解决方案的可扩展性不够。取决于您 table(钱包)的大小(行数),您迟早会看到它。并注意 biiling 层,因为它会随着行数的增加而变高。
我的建议:如果您遇到上述限制 - 您应该在您选择的客户端上编写类似于您在本例的 udf 中看到的逻辑代码