KDB использует функцию в предложении where

Есть ли способ в kdb использовать функции в запросах. предположим, у меня есть таблица со столбцами

`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)}

фильтровать выбор? я могу сделать

f:[select from t] 

и он возвращает столбец с истинным и ложным, но я не могу понять, как сделать что-то вроде строк

select from t where f[select from t]

чтобы получить все записи, где f(x) истинно


person chrise    schedule 07.09.2017    source источник
comment
Просто убедитесь, что все, что находится справа от where, оценивается как логическое значение или список логических значений.   -  person Chromozorz    schedule 08.09.2017


Ответы (5)


Да, хотя вам не нужно передавать всю таблицу в функцию, а только соответствующие столбцы:

/ 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 считается ложным) одинаковой длины.
person MdSalih    schedule 07.09.2017

В этом сценарии кажется проще работать со словарем; используя flip на t ниже:

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 если вам нужен результат в виде таблицы:

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

Другой возможностью может быть использование функционального выбора и фильтрации список имен столбцов на те, где все значения равны 1.

person James Little    schedule 07.09.2017

Какой-то вариант этого может быть интересен.

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

Обратите внимание, что c (имена столбцов) должен быть списком. Используя tbl из предыдущего ответа:

foo[tbl;`red`blue]
person notlightnorchroma    schedule 07.09.2017

Во-первых, столбцы являются булевыми векторами, поэтому вы можете использовать их «сырыми» в предложении 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

Идя за пределы вашего вопроса, чтобы сделать аргументы имен столбцов для вашей функции, вместо того, чтобы писать функцию для использования в предложении where q-SQL, используйте функциональный выбор. Здесь вы выражаете свое ограничение в виде дерева синтаксического анализа, например. (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 Синтаксический анализ деревьев и функциональных форм

person SJT    schedule 14.09.2017

Немного более общее решение, в котором вы можете указать значения для каждого столбца отдельно (`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
person nyi    schedule 31.05.2018