下面的Q代码行都会引发错误,因为当解析“ local”语句时,局部变量不在正确的范围内。
{local:1; value "local"}[]
{[local]; value "local"}[1]
{local:1; eval parse "local"}[]
{[local]; eval parse "local"}[1]
是否可以从解析的字符串内部访问局部变量?
注意:这是我正在解决的实际问题的简化,该问题是编写一个执行查询的函数,该函数接受应返回的列的列表。我想象成品看起来像这样:
getData:{[requiredColumns, condition]
value "select ",(", " sv string[requiredColumns])," from myTable where someCol=condition"
}
此查询中的condition
参数是无法识别的参数,我的确意识到我可以附加它的值而不是在字符串中引用它,但是真正的查询使用了很多局部变量,包括表格等,所以它不像在调用value
之前将所有变量从字符串中拉出一样简单。
我是KDB和Q的新手,所以如果有人有更好的方法来实现相同的效果,我很乐意接受有关在Q中实现此结果的正确方法的教育。可变访问是可能的。
答案 0 :(得分:3)
在第一个示例中,您正确地认为local不在正确的范围内,因为value正在寻找全局变量local。
解决此问题的一种方法是使用名称空间,该名称空间将全局定义变量,但只能通过调用该名称空间来访问。在下面的修改示例中,我在.ns
命名空间中定义了本地
{.ns.local:1; value ".ns.local"}[]
对于选择时遇到的问题,如果requiredColumns
是列的符号列表,则可以仅使用Take运算符#
来选择它们。
getData:{[requiredColumns] requiredColumns#myTable}
对于使用变量的更高级查询,您可能必须使用函数选择形式,here进行了解释。这将使您可以在select语句的where和by子句中包含变量
相同的函数形式示例为(无by子句,仅select和where):
getData:{[requiredColumns;condition] requiredColumns:(), requiredColumns;
?[myTable;enlist (=;`someCol;condition);0b;requiredColumns!requiredColumns]}
第一行确保requiredColumns
是一个列表,即使用户输入一个列名也是如此
答案 1 :(得分:2)
value
将在全局范围内查找变量,这就是您收到错误的原因。您可以像在函数中那样直接使用局部变量。
您的函数大部分是正确的,只需要稍加修正即可附加条件(我在下面提到了)。但是,在这种情况下,更好的方法是使用functional select。
q) t:([]id:`a`b; val:3 4)
q) gd: {?[`t;enlist (=;`val;y);0b;((),x)!(),x]}
q) gd[`id;3] / for single column
输出:
id
-
1
q) gd[`id`val;3] / for multiple columns
如果您的条件列为符号类型,请输入条件值,例如:
q) gd: {?[`t;enlist (=;`id;y);0b;((),x)!(),x]}
q) gd[`id;enlist `a]
您可以使用parse
获得qsql
查询的功能形式:
q) parse " select id,val from t where id=`a"
?
`t
,,(=;`id;,`a)
0b
`id`val!`id`val
使用字符串concat(您的函数):
q)getData:{[requiredColumns;condition] value "select ",(", " sv string[requiredColumns])," from t where id=", .Q.s1 condition}
q) getData[enlist `id;`a] / for single column
q) getData[`id`val;`a] / for multi columns