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
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