string query in a function in kdb - kdb

func:{[query] value query};
query is part of my function. I have add some like delete xxx, yyyy from (value query) and some manipulation. I am not sure why when I don't use value "query", the function doesn't work. It said it cannot find the table. So I have to use value query in the function and query is a parameter. I need to pass "select from tab" to the function.
My questions is: how do I send if the filter is a string too?
func["select from tab where a="abc""] <<< this does not work
How can I make string inside a string work?
Also, not sure why if I do
func["select from tab where date = max date"] it did not work due to length error
but func["100#select from tab where date = max date"] it works ?
The whole function is
getTable:{[query]loadHDB[];.Q.view date where date < .z.D-30;tab:(delete xxxx,yyyyy,sub,ID,subID,tID,subTID,text,gID from((value query)));remove[];update {";"sv #[s;where (s:";"vs x) like "cId=*";:;enlist""]}each eData from (update {";"sv #[s;where (s:";"vs x) like "AId=*";:;enlist""]}each eData from tab)};
remove:{[]delete tab from `.};
loadHDB:{[]value "\\l /hdb};

You can escape the quotes using backslash http://code.kx.com/wiki/Reference/BackSlash#escape
func["select from tab where a like \"abc\""]
Edit:
If tab is a HDB table then this length error could point to a column length issue (which 100# is avoiding). What does the following return?
q)checkPartition:{[dt] a!{c!{count get x} each ` sv' x,/:c:({x where not x like "*#"} key[x])except `.d}each a:(` sv' d,/:key[d:hsym `$string dt])};
q)check:checkPartition last date
q)(where{1<count distinct value x}each check)#check

I like using -3! and also -1 to print the result. If you know what your query should look like if executed from the console then after you construct your string, use -1 to print the string. It should print the query as how it would be executed by the console.
q)stst:-3!
q)"select max age by user from tab where col1 like ",stst"Hello"
"select max age by user from tab where col1 like \"Hello\""
q)/then to view how it will be executed, use -1
q)-1"select max age by user from tab where col1 like ",stst"Hello";
select max age by user from tab where col1 like "Hello"
q)/looks good

Related

Filemaker GetAsNumber on ExecuteSQL

I have a calculation for a field like this:
GetAsNumber(
ExecuteSQL (
"SELECT nb FROM something WHERE value = ?" ;
"" ;
"" ;
amount
)
)
Everything works fine as long as the returned number is single-digit. But when the SQL statement returns for example "12", then the number I get from the GetAsNumber function is suddenly 1212 instead of 12.
As I understand it, this has somehow to do with the format in which SQL results are returned, it says so in the documentation ("FileMaker Pro returns date, time, and number data in Unicode/SQL format, not in the locale of the operating system or the file.").
But I guess there must be a way to format back the result so it can be converted to a number.
The solution comes from by michael.hor257k's comment on my question:
ExecuteSQL returns an array (I wasn't aware of it, it's also not specified in the documentation where it says: "Data type returned: text"). So my problem had nothing to do with double digits (I guess I should have run more tests), but with the sql statement returning more than one result.
As in my case multiple results are always the same, I could alter my calculation in this way:
GetValue(
ExecuteSQL (
"SELECT nb FROM something WHERE value = ?" ;
"" ;
"" ;
amount
) ;
1
)
In this way I only retrieve the first result.
As michael.hor257k suggested in his comment, I could also restrict the SQL result to one row.
ExecuteSQL (
"SELECT nb FROM something WHERE value = ? FETCH FIRST ROW ONLY" ;
"" ;
"" ;
amount
)

How to get only specific rows on DB, when date range fits SQL condition on a 'tsrange' datatype? [duplicate]

I have this query:
some_id = 1
cursor.execute('
SELECT "Indicator"."indicator"
FROM "Indicator"
WHERE "Indicator"."some_id" = %s;', some_id)
I get the following error:
TypeError: 'int' object does not support indexing
some_id is an int but I'd like to select indicators that have some_id = 1 (or whatever # I decide to put in the variable).
cursor.execute('
SELECT "Indicator"."indicator"
FROM "Indicator"
WHERE "Indicator"."some_id" = %s;', [some_id])
This turns the some_id parameter into a list, which is indexable. Assuming your method works like i think it does, this should work.
The error is happening because somewhere in that method, it is probably trying to iterate over that input, or index directly into it. Possibly like this: some_id[0]
By making it a list (or iterable), you allow it to index into the first element like that.
You could also make it into a tuple by doing this: (some_id,) which has the advantage of being immutable.
You should pass query parameters to execute() as a tuple (an iterable, strictly speaking), (some_id,) instead of some_id:
cursor.execute('
SELECT "Indicator"."indicator"
FROM "Indicator"
WHERE "Indicator"."some_id" = %s;', (some_id,))
Your id needs to be some sort of iterable for mogrify to understand the input, here's the relevant quote from the frequently asked questions documentation:
>>> cur.execute("INSERT INTO foo VALUES (%s)", "bar") # WRONG
>>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar")) # WRONG
>>> cur.execute("INSERT INTO foo VALUES (%s)", ("bar",)) # correct
>>> cur.execute("INSERT INTO foo VALUES (%s)", ["bar"]) # correct
This should work:
some_id = 1
cursor.execute('
SELECT "Indicator"."indicator"
FROM "Indicator"
WHERE "Indicator"."some_id" = %s;', (some_id, ))
Slightly similar error when using Django:
TypeError: 'RelatedManager' object does not support indexing
This doesn't work
mystery_obj[0].id
This works:
mystery_obj.all()[0].id
Basically, the error reads Some type xyz doesn't have an __ iter __ or __next__ or next function, so it's not next(), or itsnot[indexable], or iter(itsnot), in this case the arguments to cursor.execute would need to implement iteration, most commonly a List, Tuple, or less commonly an Array, or some custom iterator implementation.
In this specific case the error happens when the classic string interpolation goes to fill the %s, %d, %b string formatters.
Related:
How to implement __iter__(self) for a container object (Python)
Pass parameter into a list, which is indexable.
cur.execute("select * from tableA where id =%s",[parameter])
I had the same problem and it worked when I used normal formatting.
cursor.execute(f'
SELECT "Indicator"."indicator"
FROM "Indicator"
WHERE "Indicator"."some_id" ={some_id};')
Typecasting some_id to string also works.
cursor.execute(""" SELECT * FROM posts WHERE id = %s """, (str(id), ))

An access query comparing the time part in a date field with values input in a form

I have an access query with predicates (conditions) on a date/time column called start_time. The condition is on two form fields defined with "Format" as "short time". The problem is that this query does not give correct results.
SELECT event_cust.*
FROM event_cust
WHERE Format([start_time],"hh:mm")
BETWEEN [Forms]![CustEventRptForm]![FromHour]
AND [Forms]![CustEventRptForm]![ToHour]
Also tried it using Format([start_time], "short time") BETWEEN ... - did not work either.
Do we need anything in addition to above code to get the correct results?
I have tested with literal values as shown below and I get correct results with that.
SELECT event_cust.*
FROM event_cust
WHERE Format([start_time],"hh:mm") BETWEEN '10:00' AND '13:00'
My guess is it's not interpreting the value from the form correctly.
Try adding quotes before and after the values:
SELECT event_cust.*
FROM event_cust
WHERE Format([start_time],"hh:mm") Between "" & [Forms]![CustEventRptForm]![FromHour] & ""
And "" & [Forms]![CustEventRptForm]![ToHour] & ""
Don't use string comparisons for date/times.
SELECT event_cust.*
FROM event_cust
WHERE TimeValue([start_time]) >= CDate([Forms]![CustEventRptForm]![FromHour])
AND TimeValue([start_time]) <= CDate([Forms]![CustEventRptForm]![ToHour])

Get substring into a new column

I have a table that contains a column that has data in the following format - lets call the column "title" and the table "s"
title
ab.123
ab.321
cde.456
cde.654
fghi.789
fghi.987
I am trying to get a unique list of the characters that come before the "." so that i end up with this:
ab
cde
fghi
I have tried selecting the initial column into a table then trying to do an update to create a new column that is the position of the dot using "ss".
something like this:
t: select title from s
update thedot: (title ss `.)[0] from t
i was then going to try and do a 3rd column that would be "N" number of characters from "title" where N is the value stored in "thedot" column.
All i get when i try the update is a "type" error.
Any ideas? I am very new to kdb so no doubt doing something simple in a very silly way.
the reason why you get the type error is because ss only works on string type, not symbol. Plus ss is not vector based function so you need to combine it with each '.
q)update thedot:string[title] ss' "." from t
title thedot
---------------
ab.123 2
ab.321 2
cde.456 3
cde.654 3
fghi.789 4
There are a few ways to solve your problem:
q)select distinct(`$"." vs' string title)[;0] from t
x
----
ab
cde
fghi
q)select distinct(` vs' title)[;0] from t
x
----
ab
cde
fghi
You can read here for more info: http://code.kx.com/q/ref/casting/#vs
An alternative is to make use of the 0: operator, to parse around the "." delimiter. This operator is especially useful if you have a fixed number of 'columns' like in a csv file. In this case where there is a fixed number of columns and we only want the first, a list of distinct characters before the "." can be returned with:
exec distinct raze("S ";".")0:string title from t
`ab`cde`fghi
OR:
distinct raze("S ";".")0:string t`title
`ab`cde`fghi
Where "S " defines the types of each column and "." is the record delimiter. For records with differing number of columns it would be better to use the vs operator.
A variation of WooiKent's answer using each-right (/:) :
q)exec distinct (` vs/:x)[;0] from t
`ab`cde`fghi

select first letter of different columns in oracle

I want a query which will return a combination of characters and number
Example:
Table name - emp
Columns required - fname,lname,code
If fname=abc and lname=pqr and the row is very first of the table then result should be code = ap001.
For next row it should be like this:
Fname = efg, lname = rst
Code = er002 and likewise.
I know that we can use substr to retrieve first letter of a colume but I don't know how to use it to do with two columns and how to concatenate.
OK. You know you can use substr function. Now, to concatenate you will need a concatenation operator ||. To get the number of row retrieved by your query, you need the rownum pseudocolumn. Perhaps you will also need to use to_char function to format the number. About all those functions and operators you can read in SQL reference. Anyway I think you need something like this (I didn't check it):
select substr(fname, 1, 1) || substr(lname, 1, 1) || to_char(rownum, 'fm009') code
from emp