Python retrieve individual item from fetchone() - python

I have a SQL query in python like so to retrieve the first, fourth, and fifth column elements if it exists
cur2.execute('SELECT * FROM duplicates where TITLE=?', [post_title])
sql2.commit()
if cur2.fetchone():
repost_permalink = cur.fetchone()[0]
repost_title = cur.fetchone()[3]
repost_submitter = cur.fetchone()[4]
Forr some reason I keep getting the error:
repost_permalink = cur.fetchone()[0]
TypeError: 'NoneType' object has no attribute '__getitem__'
Am I accessing the element incorrectly?

Every time you call fetchone(), it fetches another row. So you are fetching four different rows in your code, because you call fetchone four times. If there aren't that many rows in the result set, some of them will be None.
If you want to get parts of a single row, store the row and then access it:
row = cur2.fetchone()
if row:
repost_permalink = row[0]
repost_title = row[3]
repost_submitter = row[4]

Related

How to get an individual row in Big Query?

I want to get an individual row from the QueryJob in BQ. My query: select count(*) from ... returns a single row & I want to read the count value which is its first column. So if I can get the first row then I can do row[0] for the first column. I can iterate: row in queryJob but since I require only the first row this seems unneccesary.
Below is what I've tried:
row = self.client.query(count_query)
count = row.result()[0]
This gives an error:
'QueryJob' object is not subscriptable"
How can I get individual rows from queryJob by the row index?
Just do:
row = self.client.query(count_query)
result = row.result().total_rows
This will give the count from the query
you can use to_dataframe():
result = self.client.query(count_query).to_dataframe()
#if you want to result as a integer:
result = self.client.query(count_query).to_dataframe()['first_column_name'].iat[0]

Using two columns in an existing SQLite database to create a third column using Python

I have created a database with multiple columns and am wanting to use the data stored in two of the columns (named 'cost' and 'Mwe') to create a new column 'Dollar_per_KWh'. I have created two lists, one contains the rowid and the other contains the new value that I want to populate the new Dollar_per_KWh column. As it iterates through all the rows, the two lists are zipped together into a dictionary containing tuples. I then try to populate the new sqlite column. The code runs and I do not receive any errors. When I print out the dictionary it looks correct.
Issue: the new column in my database is not being updated with the new data and I am not sure why. The values in the new column are showing 'NULL'
Thank you for your help. Here is my code:
conn = sqlite3.connect('nuclear_builds.sqlite')
cur = conn.cursor()
cur.execute('''ALTER TABLE Construction
ADD COLUMN Dollar_per_KWh INTEGER''')
cur.execute('SELECT _rowid_, cost, Mwe FROM Construction')
data = cur.fetchall()
dol_pr_kW = dict()
key = list()
value = list()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
value.append(int((cost*10**6)/(MWe*10**3)))
key.append(id)
dol_pr_kW = list(zip(key, value))
cur.executemany('''UPDATE Construction SET Dollar_per_KWh = ? WHERE _rowid_ = ?''', (dol_pr_kW[1], dol_pr_kW[0]))
conn.commit()
Not sure why it isn't working. Have you tried just doing it all in SQL?
conn = sqlite3.connect('nuclear_builds.sqlite')
cur = conn.cursor()
cur.execute('''ALTER TABLE Construction
ADD COLUMN Dollar_per_KWh INTEGER;''')
cur.execute('''UPDATE Construction SET Dollar_per_KWh = cast((cost/MWe)*1000 as integer);''')
It's a lot simpler just doing the calculation in SQL than pulling data to Python, manipulating it, and pushing it back to the database.
If you need to do this in Python for some reason, testing whether this works will at least give you some hints as to what is going wrong with your current code.
Update: I see a few more problems now.
First I see you are creating an empty dictionary dol_pr_kW before the for loop. This isn't necessary as you are re-defining it as a list later anyway.
Then you are trying to create the list dol_pr_kW inside the for loop. This has the effect of over-writing it for each row in data.
I'll give a few different ways to solve it. It looks like you were trying a few different things at once (using dict and list, building two lists and zipping into a third list, etc.) that is adding to your trouble, so I am simplifying the code to make it easier to understand. In each solution I will create a list called data_to_insert. That is what you will pass at the end to the executemany function.
First option is to create your list before the for loop, then append it for each row.
dol_pr_kW = list()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
val = int((cost*10**6)/(MWe*10**3))
dol_pr_kW.append(id,val)
#you can do this or instead change above step to dol_pr_kW.append(val,id).
data_to_insert = [(r[1],r[0]) for r in dol_pr_kW]
The second way would be to zip the key and value lists AFTER the for loop.
key = list()
value = list()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
value.append(int((cost*10**6)/(MWe*10**3)))
key.append(id)
dol_pr_kW = list(zip(key,value))
#you can do this or instead change above step to dol_pr_kW=list(zip(value,key))
data_to_insert = [(r[1],r[0]) for r in dol_pr_kW]
Third, if you would rather keep it as an actual dict you can do this.
dol_pr_kW = dict()
for row in data:
id = row[0]
cost = row[1]
MWe = row[2]
val = int((cost*10**6)/(MWe*10**3))
dol_pr_kW[id] = val
# convert to list
data_to_insert = [(dol_pr_kW[id], id) for id in dol_per_kW]
Then to execute call
cur.executemany('''UPDATE Construction SET Dollar_per_KWh = ? WHERE _rowid_ = ?''', data_to_insert)
cur.commit()
I prefer the first option since it's easiest for me to understand what's happening at a glance. Each iteration of the for loop just adds a (id, val) to the end of the list. It's a little more cumbersome to build two lists independently and zip them together to get a third list.
Also note that if the dol_pr_kW list had been created correctly, passing (dol_pr_kW[1],dol_pr_kW[0]) to executemany would pass the first two rows in the list instead of reversing (key,value) to (value,key). You need to do a list comprehension to accomplish the swap in one line of code. I just did this as a separate line and assigned it to variable data_to_insert for readability.

Why is `for...in` returning a tuple when trying to iterate through rows returned by query?

I select 1 column from a table in a database. I want to iterate through each of the results. Why is it when I do this it’s a tuple instead of a single value?
con = psycopg2.connect(…)
cur = con.cursor()
stmt = "SELECT DISTINCT inventory_pkg FROM {}.{} WHERE inventory_pkg IS NOT NULL;".format(schema, tableName)
cur.execute(stmt)
con.commit()
referenced = cur.fetchall()
for destTbl in referenced:#why is destTbl a single element tuple?
print('destTbl: '+str(referenced))
stmt = "SELECT attr_name, attr_rule FROM {}.{} WHERE ppm_table_name = {};".format(schema, tableName, destTbl)#this fails because the where clause gets messed up because ‘destTbl’ has a comma after it
cur.execute(stmt)
Because that's what the db api does: always returns a tuple for each row in the result.
It's pretty simple to refer to destTbl[0] wherever you need to.
Because you are getting rows from your database, and the API is being consistent.
If your query asked for * columns, or a specific number of columns that is greater than 1, you'd also need a tuple or list to hold those columns for each row.
In other words, just because you only have one column in this query doesn't mean the API suddenly will change what kind of object it returns to model a row.
Simply always treat a row as a sequence and use indexing or tuple assignment to get a specific value out. Use:
inventory_pkg = destTbl[0]
or
inventory_pkg, = destTbl
for example.

python error: object of type 'builtin_function_or_method' has no len()

I have a problem with my current code, I'm trying to count on each 69 rows to see how many row of channels I have got in a sqlite3 database.
When I try this:
cur.execute('SELECT channel FROM programs WHERE channel GROUP BY channel')
row_count = len(cur.fetchall)
print row_count
It give me the error:
TypeError: object of type 'builtin_function_or_method' has no len()
The error are jumping on this line:
row_count = len(cur.fetchall)
Can you please help me how I can count on each 69 rows to see how many row of channels I have got in a sqlite3 database?
You are trying to get the length of te cur.fetchall method object. You didn't call the method.
You'd add () after the method name to call it and get the full results first:
row_count = len(cur.fetchall())
However, this is hardly efficient. Ask the database to get your row count instead:
cur.execute('SELECT COUNT(DISTINCT channel) FROM programs WHERE channel')
row_count, = cur.fetchone()
where I assume you meant WHERE channel to be treated as a boolean expression; a cast to NUMERIC and any rows that are non-zero are included in the count.

UPDATE each row of MySQL with different value in Python

To sum it up. I have data in a row of a db (MySQL). This data are used in the script to calculate a value. A for loop is used to calculate this value for each row in the table.
The Problem: The results stored in the variable meant have to be updated in a different column of the same row.
I tried to include the update command in the for loop but I get an error (see below). If I do not include the update-command in the for loop I just get the result of the last row but for all rows!
The script:
for row in rows:
for col in row:
x = map(str.strip,col.lower().split())
st = map(lambda wo: abo.get(wo, 0), x)
meant = numpy.meant(st)
cur.execute("""UPDATE table_x SET result = %s Where text = %s""",(meant, rows))
Unfortunately I am getting this error:
Programming Error: (1064, 'You have an error in your SQL syntax; check the manual...
How can I update the column with each calculated value (meant) of that row?
As I see rows is a list ( or an iterable )
and in your query, you are binding the placeholder with rows ( instead of row? )
cur.execute("""UPDATE table_x SET result = %s Where text = %s""",(meant, rows)
That would most probably create a syntax error.

Categories

Resources