Hello StackOverflow community.
I recently came up with an interesting tutorial/game about KQL, a I am trying to solve puzzles proposed on the site.
One of them makes use of the following function to display a map
.create-or-alter function with (docstring = "Virtual tour starts here", skipvalidation = "true") VirtualTourLink(lat:real, lon:real) {
print Link=strcat('https://www.google.com/maps/#', lat, ',', lon, ',4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192')}
I am trying to use this function with some known values (see example below)
nyc_trees
| invoke VirtualTourLink(lat=40.6777207, lon=-73.86205414)
However, the KQL compiler prompts an error stating that the function only accepts two arguments.
Do you have clues why this happen?
The body of the function is basically a print statement.
print is a tabular operator (which yield a single row); therefore, you should treat the function as a table:
VirtualTourLink(lat=40.6777207, lon=-73.86205414)
Link
https://www.google.com/maps/#40.6777207,-73.86205414,4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192
P.S.
If you want to execute the function over rows of the table you can redefine it like this (remove the print so the function will return a scalar):
.create-or-alter function with (docstring = "Virtual tour starts here", skipvalidation = "true") VirtualTourLink(lat:real, lon:real) {
strcat('https://www.google.com/maps/#', lat, ',', lon, ',4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192')}
The usage will look like this:
nyc_trees
| sample 5
| project tree_id
,latitude
,longitude
,VTL = VirtualTourLink(lat=latitude, lon=longitude)
tree_id
latitude
longitude
VTL
180683
40.72309177
-73.84421522
https://www.google.com/maps/#40.72309177,-73.84421522,4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192
200540
40.79411067
-73.81867946
https://www.google.com/maps/#40.79411067,-73.81867946,4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192
204026
40.71758074
-73.9366077
https://www.google.com/maps/#40.71758074,-73.9366077,4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192
204337
40.71353749
-73.93445616
https://www.google.com/maps/#40.71353749,-73.93445616,4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192
189565
40.66677776
-73.97597938
https://www.google.com/maps/#40.66677776,-73.97597938,4a,75y,32.0h,79.0t/data=!3m7!1e1!3m5!1s-1P!2e0!5s20191101T000000!7i16384!8i8192
Fiddle
Related
I have a list which is in below format
A = [ "machine's code" ,"max's code"]
I want to convert to that list to string and pass it to a query. I am using python for this.
I am trying with below query and not giving required results
for i in A:query=Select * from table where name='"+str(A)+"'"
Expected code should be :
Select * from table where name="machine's code"
list_of_queries = []
for element in A:
query = f'Select * from table where name="{el}"'
list_of_queries.append(query)
as pointed out by others here, this pattern should be only used internally, as it creates some sql injection security risks.
I have two sets of similar codes that gives different output. The first example does not return any output but the second example returns a output using the same search input.
First Example:
sql = "SELECT accessionID, title, ISBN, publisher, publicationYear FROM Books WHERE %s LIKE %s";
cursor.execute(sql,(col, "%" + values + "%",))
Second Example:
sql = "SELECT accessionID, title, ISBN, publisher, publicationYear FROM Books WHERE title LIKE %s";
cursor.execute(sql,("%" + values + "%",))
The codes that I am trying to code out is that WHERE is dynamic that depends on which text field user searches on. For example, if a user searches something on the title text box, it will only look into Title.
Another way I could think of is to use If conditions to hardcode, but it only works for the first If conditions and subsequent one does not work.
My question is how to make the SQL line dynamic (using first example) in the sense that I can do two %s in the SQL query line and still get the same output?
I have been trying to update some columns of a database table using cx_Oracle in Python. I created a list named check_to_process which is a result of another sql query. I am creating log_msg in the program based on success or failure and want to update same in the table only for records in check_to_process list. When I update the table without using bind variable <MESSAGE = %s>, it works fine. But when I try to use bind variable to update the columns it gives me error :
cursor.executemany("UPDATE apps.SLCAP_CITI_PAYMENT_BATCH SET MESSAGE = %s, "
TypeError: an integer is required (got type str)
Below is the code, I am using:
import cx_Oracle
connection = cx_Oracle.connect(user=os.environ['ORA_DB_USR'], password=os.environ['ORA_DB_PWD'], dsn=os.environ['ORA_DSN'])
cursor = connection.cursor()
check_to_process = ['ACHRMUS-20-OCT-2021 00:12:57', 'ACHRMUS-12-OCT-2021 16:12:01']
placeholders = ','.join(":x%d" % i for i,_ in enumerate(check_to_process))
log_msg = 'Success'
cursor.executemany("UPDATE apps.SLCAP_CITI_PAYMENT_BATCH SET MESSAGE = %s, "
"PAYMENT_FILE_CREATED_FLAG='N' "
"WHERE PAYMENT_BATCH_NAME = :1",
[(i,) for i in check_to_process], log_msg, arraydmlrowcounts=True)
Many thanks for suggestions and insights!
Your code has an odd mix of string substitution (the %s) and bind variable placeholders (the :1). And odd code that creates bind variable placeholders that aren't used. Passing log_msg the way you do isn't going to work, since executemany() syntax doesn't support string substitution.
You probably want to use some kind of IN list, as shown in the cx_Oracle documentation Binding Multiple Values to a SQL WHERE IN Clause. Various solutions are shown there, depending on the number of values and frequency that the statement will be re-executed.
Use only bind variables. You should be able to use execute() instead of executemany(). Effectively you would do:
cursor.execute("""UPDATE apps.SLCAP_CITI_PAYMENT_BATCH
SET MESSAGE = :1
WHERE PAYMENT_BATCH_NAME IN (something goes here - see the doc)""",
bind_values)
The bottom line is: read the documentation and review examples like batch_errors.py. If you still have problems, refine your question, correct it, and add more detail.
I've been given data to build an application that has sequential data in the form of part numbers of products: "000000", "000001", "000002", "000010", "000011" .... The previous application was an old MS Access database that didn't have any gap filling features in the part number generator, hence the gap between "000002" and "000010" (Yes, they are also strings, but I can work with that...).
We could continue to increment based on the last value and ignore the gaps, however, in an attempt to use all numbers available to us with our naming scheme, we'd like to be able to fill the gaps. Our naming scheme describes the "product family" with the first two digits such that: [00]0000 would be a different family from [02]0000.
I can find the starting and ending values using something like:
let query = `
LET first = (
MIN(
FOR part in part_search
SEARCH STARTS_WITH(part.PartNumber, #family)
RETURN part.PartNumber
)
)
LET last = (
MAX(
FOR part in part_search
SEARCH STARTS_WITH(part.PartNumber, #family)
RETURN part.PartNumber
)
)
RETURN { first, last }
`
The above example returns: {first: "000000", last: "000915"}
Using ArangoDB and AQL, how could I go about finding these gaps? I've found some SQL examples but I feel the features of AQL are a bit more limiting.
Thanks in advance!
To start with, I think your best bet for getting min/max values is using aggregates:
FOR part in part_search
SEARCH STARTS_WITH(part.PartNumber, #family)
COLLECT x = 1
AGGREGATE first = MIN(part.PartNumber), last = MAX(part.PartNumber)
RETURN {
first: first,
last: last
}
But that won't really help when trying to find gaps. And you're right - SQL has several logical constructs that could help (like using variables and cursor iteration), but even that would be a pattern I would discourage.
The better path might be to do a "brute force" approach - compare a table containing your existing numbers with a table of all numbers, using a native method like JOIN to find the difference. Here's how you might do that in AQL:
LET allNumbers = 0..9999
LET existingParts = (
FOR part in part_search
SEARCH STARTS_WITH(part.PartNumber, #family)
LET childId = RIGHT(part.PartNumber, 4)
RETURN TO_NUMBER(childId)
)
RETURN MINUS(allNumbers, existingParts)
The x..y construct creates a sequence (an array of numbers), which we use as the full set of possible numbers. Then, we want to return only the "non-family" part of the ID (I'm calling it "child"), which needs to be numeric to compare with the previous set. Then, we use MINUS to remove elements of existingParts from the allNumbers list.
One thing to note, that query would return only the "child" portion of the part number, so you would have to join it back to the family number later. Alternatively, you could also skip string-splitting, and get "fancy" with your list creation:
LET allNumbers = TO_NUMBER(CONCAT(#family, '0000'))..TO_NUMBER(CONCAT(#family, '9999'))
LET existingParts = (
FOR part in part_search
SEARCH STARTS_WITH(part.PartNumber, #family)
RETURN TO_NUMBER(part.PartNumber)
)
RETURN MINUS(allNumbers, existingParts)
I am stuck to find out better one between str() and format() in python
"SELECT schools.deis_income , schools.school_name,SUM(money.coin_in_amount) AS coinamount, SUM(money.note_in_amount) AS noteamount , SUM(money.coffee_coin_in_amount) AS coffeeamount , SUM(money.coin_out_amount) AS coinoutamount, SUM(money.note_out_amount) AS noteoutamount FROM money_transactions AS money JOIN school_admin_details AS sa on sa.id = money.school_admin_id JOIN schools ON schools.id=sa.school_id WHERE sa.school_id ={school_id} AND money.transaction_time BETWEEN '{start_date}' AND '{end_date}' GROUP BY schools.id".format(school_id=school_id,start_date=start_date,end_date=end_date)
I use format function here. can I use str() ?
please tell me which one give me quick result, str() or format() ???
If your question is which of this:
foo = "some text " + str(some_var) + " and some other text"
or this:
foo = "some text {} and some other text".format(var)
is "better", the general consensus is very clear: string formatting is much easier to read and maintain and the one pythonic way to go.
Now for your particular example, the answer is that both are totally wrong - unless you're ok to give full access to your database to even the most inept script kiddie. For SQL queries, the proper solution is to use prepared statements, where your db connector will take care of proper formatting and sanitizing of the values:
# assumes MySQL - for other vendors check your own
# db-api connector's doc for the correct placeholder
query = "SELECT somefield FROM mytable where somedate > %(somedate)s and something_else = %(someval)s"
cursor.execute(query, {"somedate": some_date, "someval": 42})