0

I would like to update "a" field value with column "b" value when c = `yes in hdb for date only > 2023.05.01

This is what I got so far

fncol[`:.;`tab;`a;{@[a;where c=`yes;b;a]}]

not sure if this is right and how I can apply to certain dates only

3 Answers 3

1

To apply to certain dates only you should not use fncol as this will apply to all dates. Instead have a look at fn1col (which is used in fncol):

fncol:{[dbdir;table;col;fn] / fncol[thisdb;`trade;`price;2*]
 fn1col[;col;fn]each allpaths[dbdir;table];}

From the code above you will see this uses allpaths to apply to all dates. Instead you will need to manually create a list of all dates you wish to update (listOfPaths):

fn1col[;`a;{@[a;where c=`yes;b;a]}]each listOfPaths

I think you will run into problems with your function as it references 2 columns which are not defined as local variables, namely a and b. You can fix this, but fn1col only seems to work on a single column so you may need to write your own custom function (negating the use of dbmaint).

Sign up to request clarification or add additional context in comments.

Comments

1

As Thomas mentioned, fncol is for applying a function that references 1 column's values only, you need something that can reference a,b and c.

The function should read each date partition that you're interested in, check the value of c and then create the appropriate values for the a column and write those to disk.

Create a test db:

q){(` sv hsym[`$string x],`t`)set .Q.en[`:.;]([]a:5#`a;b:5#`b;c:5?`yes`no)}each .z.d-til 3;
q)\l .
q)select count i by date,a,c from t
date       a c  | x
----------------| -
2023.07.06 a no | 3
2023.07.06 a yes| 2
2023.07.07 a no | 3
2023.07.07 a yes| 2
2023.07.08 a no | 2
2023.07.08 a yes| 3

The fn function below creates the path to the date partition, runs a vector conditional against the c column and uses amend to update the a column file on disk with the new values. (Note, you should load the db into the q process first, so that the enumerated values are correct.) The single parameter is a date, you can filter the date variable in the db to pass this appropriately.

q)fn:{d:` sv hsym[`$string x],`t;@[d;`a;:;] ?[`yes=d`c;d`b;d`a]}
q)date where date>2023.05.01
2023.07.06 2023.07.07 2023.07.08
q)fn each date where date>2023.05.01
`:2023.07.06/t`:2023.07.07/t`:2023.07.08/t
q)\l .
q)select count i by date,a,c from t
date       a c  | x
----------------| -
2023.07.06 a no | 3
2023.07.06 b yes| 2
2023.07.07 a no | 3
2023.07.07 b yes| 2
2023.07.08 a no | 2
2023.07.08 b yes| 3

Comments

0

As others have mentioned, you can create a new version of fncol which passes the current directory path into the function

fncol2:{[dbdir;table;col;fn]
 {fn1col[z;x;y@z]}[col;fn;]each allpaths[dbdir;table];};

Then within your custom lambda you can pull in other columns as required since you now have the path which contains them, for example:

fncol2[`:hdb;`table;`aCol;{[path;aCol] ?[`yes=get ` sv path,`cCol;aCol;get ` sv path,`bCol]}]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.