Python - Create a join condition from lists - python

I have two lists for two tables with their key columns
keycol1 = [col1,col2]
keycol2 = [col3,col4]
I want to frame a sql query with these two colums as join condition
for column1,column2 in zip(keycol1,keycol2):
join = "table1."+ column1 + " = " + "table2." + column2 and
qry = "select * from table1 join table2 on " + join
But this gives me an extra and at the end. How to avoid it?
Expected query:
select * from table1 join table2 on table1.col1 = table2.col3 and table1.col2 = table2.col4

Here is one way.
keycol1 = ['col1', 'col2']
keycol2 = ['col3', 'col4']
join = ' and '.join(['table1.{0} = table2.{1}'.format(c1, c2) \
for c1, c2 in zip(keycol1, keycol2)])
qry = "select * from table1 join table2 on " + join
# 'select * from table1 join table2 on table1.col1 = table2.col3 and table1.col2 = table2.col4'
Explanation
Use a list comprehension with str.format to form each condition.
Combine your conditions using ' and '.join().

You can also do it using the map function along with join:
keycol1 = ['col1', 'col2']
keycol2 = ['col3', 'col4']
for column1,column2 in zip(keycol1,keycol2):
joined = " and ".join(map(lambda c: "table1."+ c[0] + " = " + "table2." + c[1], zip(keycol1, keycol2)))
qry = "select * from table1 join table2 on " + joined
print(qry)
Output:
select * from table1 join table2 on table1.col1 = table2.col3 and table1.col2 = table2.col4

Related

SQL query with parameters

I use SQLite to merge two dataframes I have parameters in. Some work, others don't.
This works:
s = path_autre_qdv+'\\' + fichier_in
DATA = p.read_csv(s)
con = sql.connect('test_db.sqlite')
con.create_function('POWER', 2, sqlite_power)
c = con.cursor()
COM_DETAIL.to_sql('COM_DETAIL_SQL', con, if_exists='replace', index = False)
DATA.to_sql('DATA_SQL', con, if_exists='replace', index = False)
sq = """
SELECT
c.COM_CODE
,c.COM_NAME
,c.COM_LONG
,c.COM_LAT
,d.*
FROM
COM_DETAIL_SQL c
INNER JOIN
DATA_SQL d
ON POWER((c.COM_LONG - d.longitude)/ ? ,2) + POWER((c.COM_LAT - d.latitude)/ ? ,2) <= 1;
"""
par = (0.5, 0.5,)
RES = read_query(con,sq,par)
This doesn't:
s = path_autre_qdv+'\\' + fichier_in
DATA = p.read_csv(s)
con = sql.connect('test_db.sqlite')
con.create_function('POWER', 2, sqlite_power)
c = con.cursor()
COM_DETAIL.to_sql('COM_DETAIL_SQL', con, if_exists='replace', index = False)
DATA.to_sql('DATA_SQL', con, if_exists='replace', index = False)
sq = """
SELECT
c.COM_CODE
,c.COM_NAME
,c.COM_LONG
,c.COM_LAT
,d.*
FROM
COM_DETAIL_SQL c
INNER JOIN
DATA_SQL d
ON POWER((c.COM_LONG - d.longitude)/ ? ,2) + POWER((c.COM_LAT - d.latitude)/ ? ,2) <= 1
AND d.? IS NOT NULL AND d.? IS NOT NULL AND d.? IS NOT NULL;
"""
par = (0.5, 0.5,cinqv,meanv,nonentecinqv,)
RES = read_query(con,sq,par)
Difference is last filter, with three new parameters: cinqv, meanv and nonentecinqv given in input of the function, and are columns of DATA dataframe.
The error :
OperationalError: near "?": syntax error

Delete all the keys except one, but keep all the values in python dictonary

I need to create a dictionary where I am able to split all the select attributes, from table, where condition into different list, but it should have just 1 key. So far I have tried the below-
import pandas
import re
import sqlparse
query = "(select t1.id, t1.feed_id, t2.eff_dt, name, type from table1 t1 INNER JOIN table2 t2 ON ( t1.eff_dt = t2.eff_dt WHERE t2.eff_dt = CAST ( ('2020/12/20') AS DATE) and (t2.name = 'abc' or t2.name='pqr'))"
query2= "SELECT DISTINCT id, feed_id, eff_date FROM"
newInput= input('enter the eff_dt:')
new_where = '("'+newInput+'")'
query1= re.sub("(?<=WHERE t2.eff_dt = CAST \( )(.*)(?= AS DATE)", new_where , query, flags=re.IGNORECASE)
formatted_query = sqlparse.format(query1, reindent=True, keyword_case='lower')
formatted_query1 = sqlparse.format(query2, reindent=True, keyword_case='lower')
a = formatted_query.strip()
a1 = formatted_query1.strip()
newformat = a1+a
newformat.lstrip()
dict_list = newformat.split('\n')
dictOfWords = { i : dict_list[i] for i in range(0, len(dict_list) ) }
newDict = dict(zip(dictOfWords.keys(), [v.strip() if isinstance(v,str) else v for v in dictOfWords.values()]))
newDict
This takes the input from user for date and gives the output as below-
enter the eff_dt:2022/01/20
{0: 'select distinct id,',
1: 'feed_id,',
2: 'eff_date',
3: 'from(',
4: 'select t1.id,',
5: 't1.feed_id,',
6: 't2.eff_dt,',
7: 'name,',
8: 'type',
9: 'from table1 t1',
10: 'inner join table2 t2 on (t1.eff_dt = t2.eff_dt',
11: 'where t2.eff_dt = cast (("2022/01/20") as DATE)',
12: "and (t2.name = 'abc'",
13: "or t2.name='pqr'))"}
But I need the output as below-
{0: 'select distinct id,','feed_id,','eff_date','from(','select t1.id,','t1.feed_id,','t2.eff_dt,','name,','type','from table1 t1','inner join table2 t2 on (t1.eff_dt = t2.eff_dt','where t2.eff_dt = cast (("2022/01/20") as DATE)',"and (t2.name = 'abc'","or t2.name='pqr'))"}
Is there a way to do it? Remove all the keys except 1, but keep all the values in the dictionary. I would really appreciate some help.
Let's make a new dictionary.
This keeps the first key of the original dictionary as the only key and adds all the values as a list to that key.
# let d be the original dictionary
k,v = list(d.keys()), list(d.values())
new = {k[0]:v}
print(new)
I have updated your code directly, let me know if you still face errors.
import pandas
import re
import sqlparse
query = "(select t1.id, t1.feed_id, t2.eff_dt, name, type from table1 t1 INNER JOIN table2 t2 ON ( t1.eff_dt = t2.eff_dt WHERE t2.eff_dt = CAST ( ('2020/12/20') AS DATE) and (t2.name = 'abc' or t2.name='pqr'))"
query2= "SELECT DISTINCT id, feed_id, eff_date FROM"
newInput= input('enter the eff_dt:')
new_where = '("'+newInput+'")'
query1= re.sub("(?<=WHERE t2.eff_dt = CAST \( )(.*)(?= AS DATE)", new_where , query, flags=re.IGNORECASE)
formatted_query = sqlparse.format(query1, reindent=True, keyword_case='lower')
formatted_query1 = sqlparse.format(query2, reindent=True, keyword_case='lower')
a = formatted_query.strip()
a1 = formatted_query1.strip()
newformat = a1+a
newformat.lstrip()
dict_list = newformat.split('\n')
dictOfWords = { i : dict_list[i] for i in range(0, len(dict_list) ) }
newDict = dict(zip(dictOfWords.keys(), [v.strip() if isinstance(v,str) else v for v in dictOfWords.values()]))
k,v = list(newDict.keys()), list(newDict.values())
new = {k[0]:v}
new
{0: ['select distinct id,',
'feed_id,',
'eff_date',
'from(',
'select t1.id,',
't1.feed_id,',
't2.eff_dt,',
'name,',
'type',
'from table1 t1',
'inner join table2 t2 on (t1.eff_dt = t2.eff_dt',
'where t2.eff_dt = cast (("2022/01/20") as DATE)',
"and (t2.name = 'abc'",
"or t2.name='pqr'))"]}
a = {0:'zero', 1: 'one', 2: 'two'}
res = {0: list(a.values())}
print(res) # --> {0: ['zero', 'one', 'two']}

Find All Tables in a SQL query with a Python Script

Another way to say this is "find all substrings within a string"; while there's a bunch of these posts on stackoverflow already, none I've found quite get the job done.
#query variable
query = "select * from table1 a join table2 b on a.id = b.id left join table3 c on b.id = c.id where x = 5;"
query_list = query.split()
#find the adjacent word in a list
def find_adjacents(some_value, some_list):
i = some_list.index(some_value)
return some_list[i:i+2]
print('from tables:', find_adjacents("from", query_list)[1])
print('join tables:', find_adjacents("join", query_list)[1])
>>>from tables: table1
>>>join tables: table2
There should be one more join tables: table3. How do I get this to print All instances of the adjacent substring "join"?
Is this what you're after?
# Query variable
query = "select * from table1 a join table2 b on a.id = b.id left join table3 c on b.id = c.id where x = 5;"
query_list = query.split()
def find_adjacents(some_value, some_list):
val = [index for index, value in enumerate(some_list) if value == some_value]
allVal = []
for x in val:
allVal.append(some_list[x+1])
return allVal
>>> print('from tables:', find_adjacents("from", query_list))
from tables: ['table1']
>>> print('join tables:', find_adjacents("join", query_list))
join tables: ['table2', 'table3']

Dynamically passing the column name as well the values in python mysql query

This is the following code
pythonlist = ['Name','Mno']
datalist = ["qwerty",'234']
sql = "SELECT " + ",".join(pythonlist) + " FROM data WHERE name = '"+ "','".join(datalist) + "' INTO OUTFILE filename"
print(sql)
OUTPUT:
SELECT Name,Mno FROM data WHERE Name= 'qwerty','234'
DESIRED OUTPUT:
SELECT Name,Mno FROM data WHERE Name = 'qwerty' and Mno = 234
Do note the removal of quotations marks in 'mno'.
The reason I am doing this is due because the column names, as well as values corresponding it to, will change frequently
Code :
queryparams = {'Name': 'qwerty', 'Mno': '234'}
and_clause = []
[and_clause.append(' %s = %s ') for k,v in queryparams.items()]
and_clause_str = ' and '.join(and_clause)
sql = 'SELECT %s FROM data WHERE ' + and_clause_str
params = [','.join(queryparams.keys())]
for k,v in queryparams.items():
params.append(str(k))
params.append(str(v))
print(sql)
print(params)
cursor.execute(sql, params=tuple(params))
This works if you add 10/20 more items to dictionary .
Aswell as prevents SQL-injection : Using params to pass values instead of string-concatenation .
Try this:
data = {'Name': 'qwerty' , 'Mno' : '234'}
sql = "SELECT " + ", ".join(data.keys()) + " FROM data WHERE " + str(list(data.keys())[0]) + " = '" + \
str(data[list(data.keys())[0]]) + "' and " +\
str(list(data.keys())[1]) + " = " + str(data[list(data.keys())[1]])
print(sql)

How to introduce a switch breaker to perform insert every 50 lines

My current code basically does a bulk insert after iterating around all of the rows in my excel file. I want to introduce a switch breaker that will perform the insert every 50 lines.
db = Database(settings)
elt_insert_line = "INSERT INTO elt_data VALUES"
for row in r:
elt_insert_line = elt_insert_line + "(" + row[2] + ", " + row[3] + "),"
db.execute(elt_insert_line.rstrip(",")).commit().cleanup()
Using modulo operator and IF conditional
not familiar with python but i think you need something like this
db = Database(settings)
elt_insert_line = "INSERT INTO elt_data VALUES"
for row in r:
elt_insert_line = elt_insert_line + "(" + row[2] + ", " + row[3] + "),"
if r % 50 = 0 then
(
db.execute(elt_insert_line.rstrip(",")).commit().cleanup()
elt_insert_line = "INSERT INTO elt_data VALUES"
)
--one aditional at the end of the for
db.execute(elt_insert_line.rstrip(",")).commit().cleanup()

Categories

Resources