Reputation: 5165
I have this huge for loop where it seems very repitive, is there a way to reduce this code.
Or, should *handling the relationship on the database side as perhaps this is bad coding practice?
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
c.execute('''CREATE TABLE table_one
(c_1, c_2, c_3)''')
t1_items = [ ('a', 'c', 2),
('a', 'd', 3),
('a', 'e', 4),
('b', 'e', 5),]
c.executemany('INSERT INTO table_one VALUES (?,?,?)', t1_items)
c.execute('''CREATE TABLE table_two
(c_1, c_2, c_3, c_4, c_5, c_6, c_7,
c_8, c_9, c_10, c_11, c_12, c_13, c_14,
c_15, c_16, c_17, c_18, c_19, c_20, c_21,
c_22, c_23, c_24, c_25, c_26, c_27, c_28,
c_29, c_30, c_31, c_32, c_33, c_34, c_35,
c_36, c_37, c_38, c_39, c_40)''')
t2_items = [ ('c', 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 4),
('d', 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 2, 6, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1),
('e', 1, 1, 1, 4, 1, 1, 1, 2, 5, 1, 3, 1, 1, 1, 5, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 7, 1),]
c.executemany('''INSERT INTO table_two VALUES
(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,
?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', t2_items)
c.execute('''CREATE TABLE table_three
(c_1, c_2, c_3,
v_1, v_2, v_3, v_4, v_5, v_6, v_7,
v_8, v_9, v_10, v_11, v_12, v_13, v_14,
v_15, v_16, v_17, v_18, v_19, v_20, v_21,
v_22, v_23, v_24, v_25, v_26, v_27, v_28,
v_29, v_30, v_31, v_32, v_33, v_34, v_35,
v_36, v_37, v_38, v_39, v_40)''')
sql = """SELECT t.c_1, t.c_2, t.c_3,
s.c_1, s.c_2, s.c_3, s.c_4, s.c_5, s.c_6, s.c_7,
s.c_8, s.c_9, s.c_10, s.c_11, s.c_12, s.c_13, s.c_14,
s.c_15, s.c_16, s.c_17, s.c_18, s.c_19, s.c_20, s.c_21,
s.c_22, s.c_23, s.c_24, s.c_25, s.c_26, s.c_27, s.c_28,
s.c_29, s.c_30, s.c_31, s.c_32, s.c_33, s.c_34, s.c_35,
s.c_36, s.c_37, s.c_38, s.c_39, s.c_40
FROM table_one t
INNER JOIN table_two s
ON t.c_2 = s.c_1"""
result = c.execute(sql).fetchall()
for row in result:
v_1 = row[3]*row[2]
v_2 = row[4]*row[2]
v_3 = row[5]*row[2]
v_4 = row[6]*row[2]
v_5 = row[7]*row[2]
v_6 = row[8]*row[2]
v_7 = row[9]*row[2]
v_8 = row[10]*row[2]
v_9 = row[11]*row[2]
v_10 = row[12]*row[2]
v_11 = row[13]*row[2]
v_12 = row[14]*row[2]
v_13 = row[15]*row[2]
v_14 = row[16]*row[2]
v_15 = row[17]*row[2]
v_16 = row[18]*row[2]
v_17 = row[19]*row[2]
v_18 = row[20]*row[2]
v_19 = row[21]*row[2]
v_20 = row[22]*row[2]
v_21 = row[23]*row[2]
v_22 = row[24]*row[2]
v_23 = row[25]*row[2]
v_24 = row[26]*row[2]
v_25 = row[27]*row[2]
v_26 = row[28]*row[2]
v_27 = row[29]*row[2]
v_28 = row[30]*row[2]
v_29 = row[31]*row[2]
v_30 = row[32]*row[2]
v_31 = row[33]*row[2]
v_32 = row[34]*row[2]
v_33 = row[35]*row[2]
v_34 = row[36]*row[2]
v_35 = row[37]*row[2]
v_36 = row[38]*row[2]
v_37 = row[39]*row[2]
v_38 = row[40]*row[2]
v_39 = row[41]*row[2]
v_40 = row[42]*row[2]
item = [(row[0], row[1], row[2],
v_1, v_2, v_3, v_4, v_5, v_6, v_7,
v_8, v_9, v_10, v_11, v_12, v_13, v_14,
v_15, v_16, v_17, v_18, v_19, v_20, v_21,
v_22, v_23, v_24, v_25, v_26, v_27, v_28,
v_29, v_30, v_31, v_32, v_33, v_34, v_35,
v_36, v_37, v_38, v_39, v_40),]
c.executemany('''INSERT INTO table_three VALUES
(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,
?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', item)
conn.commit()
for row in c.execute('SELECT * FROM table_three'):
print(row)
conn.close()
The code runs but I think maybe the main operation in the for loop should be replaced somehow to handle the relationship on the database side? Or just cut down the for loop with some function? Im stuck here!
EDIT: In the real code all the v_1, v_2, ... have very different unique names
EDIT 2: So i changed the code as per the answer below to
sql = """INSERT INTO table_three(c_1, c_2, c_3, v_1, v_2, v_3, v_4, v_5, v_6, v_7, v_8, v_9, v_10, v_11, v_12, v_13, v_14, v_15, v_16, v_17, v_18, v_19, v_20, v_21, v_22, v_23, v_24, v_25, v_26, v_27, v_28, v_29, v_30, v_31, v_32, v_33, v_34, v_35, v_36, v_37, v_38, v_39, v_40)
SELECT
t.c_1,
t.c_2,
t.c_3,
s.c_1 * t.c_3,
s.c_2 * t.c_3,
s.c_3 * t.c_3,
s.c_4 * t.c_3,
s.c_5 * t.c_3,
s.c_6 * t.c_3,
s.c_7 * t.c_3,
s.c_8 * t.c_3,
s.c_9 * t.c_3,
s.c_10 * t.c_3,
s.c_11 * t.c_3,
s.c_12 * t.c_3,
s.c_13 * t.c_3,
s.c_14 * t.c_3,
s.c_15 * t.c_3,
s.c_16 * t.c_3,
s.c_17 * t.c_3,
s.c_18 * t.c_3,
s.c_19 * t.c_3,
t.c_30 * t.c_3,
t.c_31 * t.c_3,
t.c_32 * t.c_3,
t.c_33 * t.c_3,
t.c_34 * t.c_3,
t.c_35 * t.c_3,
t.c_36 * t.c_3,
t.c_37 * t.c_3,
t.c_38 * t.c_3,
t.c_39 * t.c_3,
s.c_30 * t.c_3,
s.c_31 * t.c_3,
s.c_32 * t.c_3,
s.c_33 * t.c_3,
s.c_34 * t.c_3,
s.c_35 * t.c_3,
s.c_36 * t.c_3,
s.c_37 * t.c_3,
s.c_38 * t.c_3,
s.c_39 * t.c_3,
s.c_40 * t.c_3,
FROM table_one t
INNER JOIN table_two s
ON t.c_2 = s.c_1;"""
c.execute(sql)
but now i get the error
c.execute(sql)
sqlite3.OperationalError: near "FROM": syntax error
Upvotes: 0
Views: 48
Reputation: 521209
This is massively inefficient, because it is forcing you to materialize two entire result sets into Python's memory, only to write that same modified information out to your SQL database again. Try using an INSERT INTO ... SELECT
here:
INSERT INTO table_three (c_1, c_2, c_3, v_1, v_2, ..., v_40)
SELECT
t.c_1,
t.c_2,
t.c_3,
t.c_3 * t.c_2,
t.c_4 * t.c_2,
...
t.c_42 * t.c_2
FROM table_one t
INNER JOIN table_two s
ON t.c_2 = s.c_1;
I did not give Python code, and my query might be slightly off (I see a column count discrepancy in the code you posted). The basic idea here is to avoid the result set from the join select between the first two tables from ever having to leave the database, and make a round trip to and from your Python application.
Upvotes: 1