1

我有 aq 表,其中没有。非键列的数量是可变的。此外,这些列名的名称中包含一个整数。我想在这些列上执行一些功能而不实际使用它们的实际名称

我怎样才能做到这一点?

例如:

 table:   

 a |  col10  col20 col30 

 1 |    2      3     4
 2 |    5      7     8

 // Assume that I have numbers 10, 20 ,30 obtained from column names

    I want something like **update NewCol:10*col10+20*col20+30*col30 from table**

     except that no.of columns is not fixed so are their inlcluded numbers
4

4 回答 4

7

我们想使用功能更新(此处显示的简单示例:http: //www.timestored.com/kdb-guides/functional-queries-dynamic-sql#functional-update

对于这个特定的查询,我们想要生成 select 子句的计算树,即功能更新语句的最后一部分。最简单的方法是解析类似的语句,然后重新创建该格式:

q)/ create our table
q)t:([] c10:1 2 3; c20:10 20 30; c30:7 8 9; c40:0.1*4 5 6)
q)t
c10 c20 c30 c40
---------------
1   10  7   0.4
2   20  8   0.5
3   30  9   0.6

q)parse "update r:(10*c10)+(20*col20)+(30*col30) from t"
!
`t
()
0b
(,`r)!,(+;(*;10;`c10);(+;(*;20;`col20);(*;30;`col30)))
q)/ notice the last value, the parse tree
q)/ we want to recreate that using code
q){(*;x;`$"c",string x)} 10
*
10
`c10
q){(+;x;y)} over {(*;x;`$"c",string x)} each 10 20
+
(*;10;`c10)
(*;20;`c20)
q)makeTree:{{(+;x;y)} over {(*;x;`$"c",string x)} each x}

/ now write as functional update
q)![t;();0b; enlist[`res]!enlist makeTree 10 20 30]
c10 c20 c30 c40 res
-------------------
1   10  7   0.4 420
2   20  8   0.5 660
3   30  9   0.6 900

q)update r:(10*c10)+(20*c20)+(30*c30) from t
c10 c20 c30 c40 r
-------------------
1   10  7   0.4 420
2   20  8   0.5 660
3   30  9   0.6 900
于 2014-06-18T14:54:22.020 回答
2

我认为功能选择(如@Ryan 所建议的)是如果表非常通用的方法,即列名可能会变化并且列数是未知的。

然而我更喜欢@JPC 使用向量来解决乘法和求和问题的方式,即update res:sum 10 20 30*(col10;col20;col30) from table

让我们将这两种方法与一些极端情况结合起来:

q)show t:1!flip(`a,`$((10?2 3 4)?\:.Q.a),'string 10?10)!enlist[til 100],0N 100#1000?10
a | vltg4 pnwz8 mifz5 pesq7 fkcx4 bnkh7 qvdl5 tl5 lr2 lrtd8
--| -------------------------------------------------------
0 | 3     3     0     7     9     5     4     0   0   0
1 | 8     4     0     4     1     6     0     6   1   7
2 | 4     7     3     0     1     0     3     3   6   4
3 | 2     4     2     3     8     2     7     3   1   7
4 | 3     9     1     8     2     1     0     2   0   2
5 | 6     1     4     5     3     0     2     6   4   2
..
q)show n:"I"$string[cols get t]inter\:.Q.n
4 8 5 7 4 7 5 5 2 8i
q)show c:cols get t
`vltg4`pnwz8`mifz5`pesq7`fkcx4`bnkh7`qvdl5`tl5`lr2`lrtd8
q)![t;();0b;enlist[`res]!enlist({sum x*y};n;enlist,c)]
a | vltg4 pnwz8 mifz5 pesq7 fkcx4 bnkh7 qvdl5 tl5 lr2 lrtd8 res
--| -----------------------------------------------------------
0 | 3     3     0     7     9     5     4     0   0   0     176
1 | 8     4     0     4     1     6     0     6   1   7     226
2 | 4     7     3     0     1     0     3     3   6   4     165
3 | 2     4     2     3     8     2     7     3   1   7     225
4 | 3     9     1     8     2     1     0     2   0   2     186
5 | 6     1     4     5     3     0     2     6   4   2     163
..
于 2014-06-18T15:47:14.007 回答
1

Here is another solution which is also faster.

t,'([]res:(+/)("I"$(string tcols) inter\: .Q.n) *' (value t) tcols:(cols t) except  keys t)

By spending some time, we can decrease the word count as well. Logic goes like this:

a:"I"$(string tcols) inter\: .Q.n

Here I am first extracting out the integers from column names and storing them in a vector. Variable 'tcols' is declared at the end of query which is nothing but columns of table except key columns.

b:(value t) tcols:(cols t) except keys t

Here I am extracting out each column vector.

c:(+/) a *' b

Multiplying each column vector(var b) by its integer(var a) and adding corresponding values from each resulting list.

t,'([]res:c)

Finally storing result in a temp table and joining it to t.

于 2014-06-18T20:11:04.123 回答
1

您可以像@Ryan Hamilton 所指出的那样创建功能表单查询,总体而言,这将是最好的方法,因为它非常灵活。但如果你只是想把这些加起来,乘以一些权重,我喜欢通过其他途径。

编辑:错过了您所说的列名称中的数字可能会有所不同,在这种情况下您可以轻松调整它。如果列名都以相同数量的字母开头,只需删除它们,然后将剩余的解析为 int 或你有什么。否则,如果数字嵌入在文本中,请查看其他问题

//Create our table with a random number of columns (up to 9 value columns) and 1 key column
q)show t:1!flip (`$"c",/:string til n)!flip -1_(n:2+first 1?10) cut neg[100]?100
c0| c1 c2 c3 c4 c5 c6 c7 c8 c9
--| --------------------------
28| 3  18 66 31 25 76 9  44 97
60| 35 63 17 15 26 22 73 7  50
74| 64 51 62 54 1  11 69 32 61
8 | 49 75 68 83 40 80 81 89 67
5 | 4  92 45 39 57 87 16 85 56
48| 88 34 55 21 12 37 53 2  41
86| 52 91 79 33 42 10 98 20 82
30| 71 59 43 58 84 14 27 90 19
72| 0  99 47 38 65 96 29 78 13

q)update res:sum (1+til -1+count cols t)*flip value t from t
c0| c1 c2 c3 c4 c5 c6 c7 c8 c9 res
--| -------------------------------
28| 3  18 66 31 25 76 9  44 97 2230
60| 35 63 17 15 26 22 73 7  50 1551
74| 64 51 62 54 1  11 69 32 61 1927
8 | 49 75 68 83 40 80 81 89 67 3297
5 | 4  92 45 39 57 87 16 85 56 2582
48| 88 34 55 21 12 37 53 2  41 1443
86| 52 91 79 33 42 10 98 20 82 2457
30| 71 59 43 58 84 14 27 90 19 2134
72| 0  99 47 38 65 96 29 78 13 2336

q)![t;();0b; enlist[`res]!enlist makeTree 1+til -1+count cols t] ~ update res:sum (1+til -1+count cols t)*flip value t from t
1b

q)\ts do[`int$1e4;![t;();0b; enlist[`res]!enlist makeTree 1+til 9]]
232 3216j
q)\ts do[`int$1e4;update nc:sum (1+til -1+count cols t)*flip value t from t]
69 2832j

我没有在一张大桌子上测试过这个,所以请注意购买者

于 2014-06-18T15:19:19.310 回答