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
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).
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
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]}]