使用解析或值(KDB / Q)从字符串中访问局部范围的变量

时间:2019-05-04 17:43:36

标签: kdb

下面的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中实现此结果的正确方法的教育。可变访问是可能的。

2 个答案:

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

Using 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