Search code examples
kdb

How can I efficiently convert the output of one KDB function into three table columns?


I have a function that takes as input some of the values in a table and returns a tuple if you will - three separate return values, which I want to transpose into the output of a query. Here's a simplified example of what I want to achieve:

multiplier:{(x*2;x*3;x*3)};
select twoX:multiplier[price][0]; threeX:multiplier[price][1]; fourX:multiplier[price][2] from data;

The above basically works (I think I've got the syntax right for the simplified example - if not then hopefully my intention is clear), but is inefficient because I'm calling the function three times and throwing away most of the output each time. I want to rewrite the query to only call the function once, and I'm struggling.

Update

I think I missed a crucial piece of information in my explanation of the problem which affects the outcome - I need to get other data in the query alongside the output of my function. Here's a hopefully more realistic example:

multiplier:{(x*2;x*3;x*4)};
select average:avg price, total:sum price, twoX:multiplier[sum price][0]; threeX:multiplier[sum price][1]; fourX:multiplier[sum price][2] by category from data;

I'll have a go at adapting your answers to fit this requirement anyway, and apologies for missing this bit of information. The real function if a proprietary and fairly complex algorithm and the real query has about 30 output columns, hence the attempt at simplifying the example :)


Solution

  • If you're just looking for the results themselves you can extract (exec) as lists, create dictionary and then flip the dictionary into a table:

    q)exec flip`twoX`threeX`fourX!multiplier[price] from ([]price:til 10)
    twoX threeX fourX
    -----------------
    0    0      0
    2    3      4
    4    6      8
    6    9      12
    8    12     16
    10   15     20
    12   18     24
    14   21     28
    16   24     32
    18   27     36
    

    If you need other columns from the original table too then its trickier but you could join the tables sideways using ,'

    q)t:([]price:til 10)
    q)t,'exec flip`twoX`threeX`fourX!multiplier[price] from t