KDB 在 where 子句中使用函数

KDB using function in where clause

kdb 有没有办法在查询中使用函数。假设我有一个 table 列

`red`blue`green`yellow`white`purple

其中包含值 0 或 1。而不是查询

select where ((red=1) or (green=1))

我可以使用像

这样的函数吗
isRG:{((select green from x)=1) or ((select red from x)=1)}

要过滤一个select? 我可以

f:[select from t] 

它 returns 是一个包含真假的列,但我不知道如何按照

的方式做某事
select from t where f[select from t]

获取 f(x) 为真的所有条目

在这种情况下使用字典似乎更容易;在下面的 t 上使用 flip

q)t
red blue green yellow white purple
----------------------------------
0   1    0     1      1     0
q)
q)(key[x:flip[t]] where (raze value x=1))#x
blue  | 1
yellow| 1
white | 1

enlist 如果您希望结果为 table:

q)enlist (key[x:flip[t]] where (raze value x=1))#x
blue yellow white
-----------------
1    1      1

另一种可能是使用 functional select 并将列名列表过滤为所有值都等于 1 的列表。

是 - 尽管您不需要将整个 table 传递到函数中,只需传递相关的列:

/ define a table
tbl:flip`red`blue`green`yellow`white`purple!(0N;6)#36?0b;
    red blue green yellow white purple
    ----------------------------------
    1   0    0     0      1     1     
    1   0    0     0      0     1     
    1   0    0     0      0     0     
    0   0    1     0      0     0     
    1   1    0     0      0     0     
    0   0    0     0      1     0     

/ define a function to work on 2 columns - this func simply does or between the columns 
f:{[column1;column2] column1|column2};

/ use function on 2 columns of table
select from tbl where f[red;green]
    red blue green yellow white purple
    ----------------------------------
    1   0    0     0      1     1     
    1   0    0     0      0     1     
    1   0    0     0      0     0     
    0   0    1     0      0     0     
    1   1    0     0      0     0     

在 select where 子句中使用函数时要记住的主要原则是:

  • 每个列参数都作为向量传入
  • 函数返回的值必须是相同长度的布尔值向量(或布尔值等价类型,例如整数,因为 0 被视为假)

这方面的一些变体可能很有趣。

foo:{[t;c] t where (|) over flip c#t}

注意c(列名)需要是一个列表。使用之前回复的 tbl:

foo[tbl;`red`blue]

首先,列是布尔向量,因此您可以在 where 子句中使用它们的“原始”:

q)tbl
red blue green yellow white purple
----------------------------------
0   0    1     0      0     0
1   0    1     1      0     0
1   0    1     1      1     0
0   0    0     0      0     0
0   1    0     0      1     1
1   0    1     1      0     0
q)select from tbl where red or green
red blue green yellow white purple
----------------------------------
0   0    1     0      0     0
1   0    1     1      0     0
1   0    1     1      1     0
1   0    1     1      0     0

可以在where子句中使用自己的函数吗?绝对。

q)isRG:{or/[x`red`green]}
q)isRG tbl
111001b
q)select from tbl where isRG tbl
red blue green yellow white purple
----------------------------------
0   0    1     0      0     0
1   0    1     1      0     0
1   0    1     1      1     0
1   0    1     1      0     0

超越你的问题,将列名称作为你函数的参数,而不是编写一个函数在 q -SQL where 子句,使用 functional select. In this, you express your constraint as a parse tree,例如(or;`red;`white)

q)?[tbl; enlist(or; `red; `white); 0b; ()]
red blue green yellow white purple
----------------------------------
1   0    1     1      0     0
1   0    1     1      1     0
0   1    0     0      1     1
1   0    1     1      0     0

然后您可以参数化列名:

q)selEither:{[t; c1; c2] ?[t; enlist(or; c1 ;c2); 0b; ()]}
q)selEither[tbl; `red; `white]
red blue green yellow white purple
----------------------------------
1   0    1     1      0     0
1   0    1     1      1     0
0   1    0     0      1     1
1   0    1     1      0     0

最后,您可以将其从一对扩展为 列表 列名称:

q)selAny:{[tbl; cn] ?[tbl; enlist(or/;enlist,cn); 0b; ()]}
q)selAny[t; `white`green`yellow]
…

在 KX 技术白皮书中查看更多信息 Parse Trees and Functional Forms

一个稍微更通用的解决方案,当值不是布尔值时,您可以分别指定每个列的值 (`red`blue`green;1 1 0)

q)t:`red`blue`green`yellow`white`purple!/:(1 0 1 0 1 0;1 1 1 0 0 0;0 0 0 0 1 1)

/Create a 'where' clause dynamically 
q)df:{{(or;x;y)}over{(=;x 0;x 1)} each flip x}

/test 
q)df (`red`blue`green;1 1 0)
(|;(|;(=;`red;1j);(=;`blue;1j));(=;`green;0j))

/functional select 
f2:{[tab;cl;df]?[tab;enlist (df[cl];::);0b;()!()]}

/Projection using the df with f2 function 
f:f2[;;df]

/Calling the function 
f[t;(`red`blue`green;1 1 0)]
red blue green yellow white purple
----------------------------------
1   0    1     0      1     0
1   1    1     0      0     0
0   0    0     0      1     1