kdbqsqlquery

Changing a functional qSQL query to involve multiple columns in calculation KDB+/Q


I have a ? exec query like so:

t:([]Quantity: 1 2 3;Price 4 5 6;date:2020.01.01 2020.01.02 2020.01.03);
?[t;enlist(within;`date;(2020.01.01,2020.01.02));0b;(enlist `Quantity)!enlist (sum;(`Quantity))]

to get me the sum of the Quantity in the given date range. I want to adjust this to get me the sum of the Notional in the date range; Quantity*Price. So the result should be (1x4)+(2x5)=14.

I tried things like the following

?[t;enlist(within;`date;(2020.01.01,2020.01.02));0b;(enlist `Quantity)!enlist (sum;(`Price*`Quantity))]

but couldn't get it to work. Any advice would be greatly appreciated!


Solution

  • I would advise in such a scenario to think about the qSql style query that you are looking for and then work from there.

    So in this case you are looking, I believe, to do something like:

    select sum Quantity*Price from t where date within 2020.01.01 2020.01.02
    

    You can then run parse on this to break it into its function form i.e the ? exec query you refer to.

        q)parse"select sum Quantity*Price from t where date within 2020.01.01 2020.01.02"
    ?
    `t
    ,,(within;`date;2020.01.01 2020.01.02)
    0b
    (,`Quantity)!,(sum;(*;`Quantity;`Price))
    

    This is your functional form that you need; table, where clause, by and aggregation.

    You can see your quantity here is just the sum of the multiplication of the two columns.

    q)?[t;enlist(within;`date;(2020.01.01;2020.01.02));0b;enlist[`Quantity]!enlist(sum;(*;`Quantity;`Price))]
    Quantity
    --------
    14
    

    You could also extend this to change the column as necessary and create a function for it too, if you so wish:

    q)calcNtnl:{[sd;ed] ?[t;enlist(within;`date;(sd;ed));0b;enlist[`Quantity]!enlist(sum;(*;`Quantity;`Price))]}
    q)calcNtnl[2020.01.01;2020.01.02]
    Quantity
    --------
    14