KDB/Q-Sql 中选定行的条件分组依据
Conditional Group By on Selected rows in KDB/Q-Sql
我有一个要求,我必须执行多个查询并在具有 where 子句的列上执行分组,按列分组是固定的,并且 where 条件将在具有可变条件的固定列上执行。只有列名和聚合类型会有所不同
例如,如果我有 table :
k1 k2 val1 val2
1 1 10 30
1 1 20 31
1 2 30 32
2 2 40 33
2 3 50 34
2 4 60 35
2 4 70 36
3 4 80 37
3 5 90 38
3 5 100 39
t:([] k1:1 1 1 2 2 2 2 3 3 3; k2:1 1 2 2 3 4 4 4 5 5; val1:10 20 30 40 50 60 70 80 90 100; val2:31 31 32 33 34 35 36 37 38 39)
我需要执行的查询如下
select avg_val1:avg val1 by k1 from t where k2 in 2 3 4
select sum_val1:sum val1 by k1 from t where k2 in 2 3
select sum_val2:sum val2 by k1 from t where k2 in 2 3 5
select min_val2:min val2 by k1 from t where k2 in 1 2 3 4 5
我想使用函数查询在单次执行中执行这些查询。我试过了,但无法设置正确的条件和语法
res:?[t;();(enlist`k1)!enlist`k1;(`avg_val1;`sum_val2)!({$[x; y; (::)]}[1b;(avg;`val1)];{$[x; y; (::)]}[1b; (sum;`val2)])];
k1 avg_val1 sum_val2
1 20.0 94
2 55.0 138
3 90.0 114
而不是将 1b 置于条件中,我想像这样放置真实条件:
res:?[t;();(enlist`k1)!enlist`k1;(`avg_val1;`sum_val2)!({$[x; y; (::)]}[(in;`k2;2 3 4i);(avg;`val1)];{$[x; y; (::)]}[(in;`k2;2 3i); (sum;`val2)])];
但它会给出“类型”错误,因为查询将首先按 k1 分组,而 k2 将是列表。所以条件也不对。
我想知道最好的解决方案是什么。
可能会有更好的方法来解决同样的问题。
请帮助我。
谢谢。
vector conditional (?) operator 可以让您更接近您想要的。
鉴于您的 table
t:([] k1:1 1 1 2 2 2 2 3 3 3; k2:1 1 2 2 3 4 4 4 5 5; val1:10 20 30 40 50 60 70 80 90 100; val2:31 31 32 33 34 35 36 37 38 39)
k1 k2 val1 val2
---------------
1 1 10 31
1 1 20 31
1 2 30 32
2 2 40 33
2 3 50 34
2 4 60 35
2 4 70 36
3 4 80 37
3 5 90 38
3 5 100 39
您可以更新 val1
列以在条件不成立时保留空值
update val1:?[k2 in 2 3 4;val1;0N] from t
k1 k2 val1 val2
---------------
1 1 31
1 1 31
1 2 30 32
2 2 40 33
2 3 50 34
2 4 60 35
2 4 70 36
3 4 80 37
3 5 38
3 5 39
再做一些工作,您可以获得所需的聚合(注意:聚合函数忽略空值)
select avg ?[k2 in 2 3 4;val1;0N] by k1 from t
k1| x
--| --
1 | 30
2 | 55
3 | 80
你可以把它包装成一个功能性的 select 语句,像这样
?[t;();{x!x}enlist`k1;`avg_val1`sum_val2!((avg;(?;(in;`k2;2 3 4);`val1;0N));(sum;(?;(in;`k2;2 3);`val2;0N)))]
k1| avg_val1 sum_val2
--| -----------------
1 | 30 32
2 | 55 67
3 | 80 0
但是,当您使用不忽略空值的函数时,这可能会中断,例如count
。您最好在 select 语句中使用 where 运算符:
select avg val1 where k2 in 2 3 4 by k1 from t
k1| x
--| --
1 | 30
2 | 55
3 | 80
?[t;();{x!x}enlist`k1;`avg_val1`sum_val2!((avg;(`val1;(where;(in;`k2;2 3 4))));(sum;(`val2;(where;(in;`k2;2 3)))))]
k1| avg_val1 sum_val2
--| -----------------
1 | 30 32
2 | 55 67
3 | 80 0
我有一个要求,我必须执行多个查询并在具有 where 子句的列上执行分组,按列分组是固定的,并且 where 条件将在具有可变条件的固定列上执行。只有列名和聚合类型会有所不同 例如,如果我有 table :
k1 k2 val1 val2
1 1 10 30
1 1 20 31
1 2 30 32
2 2 40 33
2 3 50 34
2 4 60 35
2 4 70 36
3 4 80 37
3 5 90 38
3 5 100 39
t:([] k1:1 1 1 2 2 2 2 3 3 3; k2:1 1 2 2 3 4 4 4 5 5; val1:10 20 30 40 50 60 70 80 90 100; val2:31 31 32 33 34 35 36 37 38 39)
我需要执行的查询如下
select avg_val1:avg val1 by k1 from t where k2 in 2 3 4
select sum_val1:sum val1 by k1 from t where k2 in 2 3
select sum_val2:sum val2 by k1 from t where k2 in 2 3 5
select min_val2:min val2 by k1 from t where k2 in 1 2 3 4 5
我想使用函数查询在单次执行中执行这些查询。我试过了,但无法设置正确的条件和语法
res:?[t;();(enlist`k1)!enlist`k1;(`avg_val1;`sum_val2)!({$[x; y; (::)]}[1b;(avg;`val1)];{$[x; y; (::)]}[1b; (sum;`val2)])];
k1 avg_val1 sum_val2
1 20.0 94
2 55.0 138
3 90.0 114
而不是将 1b 置于条件中,我想像这样放置真实条件:
res:?[t;();(enlist`k1)!enlist`k1;(`avg_val1;`sum_val2)!({$[x; y; (::)]}[(in;`k2;2 3 4i);(avg;`val1)];{$[x; y; (::)]}[(in;`k2;2 3i); (sum;`val2)])];
但它会给出“类型”错误,因为查询将首先按 k1 分组,而 k2 将是列表。所以条件也不对。
我想知道最好的解决方案是什么。 可能会有更好的方法来解决同样的问题。 请帮助我。
谢谢。
vector conditional (?) operator 可以让您更接近您想要的。
鉴于您的 table
t:([] k1:1 1 1 2 2 2 2 3 3 3; k2:1 1 2 2 3 4 4 4 5 5; val1:10 20 30 40 50 60 70 80 90 100; val2:31 31 32 33 34 35 36 37 38 39)
k1 k2 val1 val2
---------------
1 1 10 31
1 1 20 31
1 2 30 32
2 2 40 33
2 3 50 34
2 4 60 35
2 4 70 36
3 4 80 37
3 5 90 38
3 5 100 39
您可以更新 val1
列以在条件不成立时保留空值
update val1:?[k2 in 2 3 4;val1;0N] from t
k1 k2 val1 val2
---------------
1 1 31
1 1 31
1 2 30 32
2 2 40 33
2 3 50 34
2 4 60 35
2 4 70 36
3 4 80 37
3 5 38
3 5 39
再做一些工作,您可以获得所需的聚合(注意:聚合函数忽略空值)
select avg ?[k2 in 2 3 4;val1;0N] by k1 from t
k1| x
--| --
1 | 30
2 | 55
3 | 80
你可以把它包装成一个功能性的 select 语句,像这样
?[t;();{x!x}enlist`k1;`avg_val1`sum_val2!((avg;(?;(in;`k2;2 3 4);`val1;0N));(sum;(?;(in;`k2;2 3);`val2;0N)))]
k1| avg_val1 sum_val2
--| -----------------
1 | 30 32
2 | 55 67
3 | 80 0
但是,当您使用不忽略空值的函数时,这可能会中断,例如count
。您最好在 select 语句中使用 where 运算符:
select avg val1 where k2 in 2 3 4 by k1 from t
k1| x
--| --
1 | 30
2 | 55
3 | 80
?[t;();{x!x}enlist`k1;`avg_val1`sum_val2!((avg;(`val1;(where;(in;`k2;2 3 4))));(sum;(`val2;(where;(in;`k2;2 3)))))]
k1| avg_val1 sum_val2
--| -----------------
1 | 30 32
2 | 55 67
3 | 80 0