I am struggling to use the output of a raw query. My code is as follows:
cursor.execute("select f.fixturematchday, u.teamselection1or2, u.teamselectionid,u.user_id from straightred_fixture f, straightred_userselection u where u.user_id = 349 and f.fixtureid = u.fixtureid and f.fixturematchday=6 order by u.teamselection1or2")
currentSelectedTeams = cursor.fetchone()
if not currentSelectedTeams:
currentSelectedTeam1 = 0
currentSelectedTeam2 = 0
else:
currentSelectedTeam1 = currentSelectedTeams[0].teamselectionid
currentSelectedTeam2 = currentSelectedTeams[1].teamselectionid
I get the following error:
currentSelectedTeam1 = currentSelectedTeams[0].teamselectionid
AttributeError: 'long' object has no attribute 'teamselectionid'
Any help would be appreciated, many thanks in advance, Alan.
PS
In case it helps the result of my query in MySQL is as follows:
mysql> select f.fixturematchday, u.teamselection1or2, u.teamselectionid,u.user_id from straightred_fixture f, straightred_userselection u where u.user_id = 349 and f.fixtureid = u.fixtureid and f.fixturematchday=6 order by u.teamselection1or2;
+-----------------+-------------------+-----------------+---------+
| fixturematchday | teamselection1or2 | teamselectionid | user_id |
+-----------------+-------------------+-----------------+---------+
| 6 | 1 | 31 | 349 |
| 6 | 2 | 21 | 349 |
+-----------------+-------------------+-----------------+---------+
2 rows in set (0.00 sec)
Your issue is that you are using cursor.fetchone() and iterating through the result expecting it to return multiple rows.
If you want the top 2 results, you might want to use fetchmany and limit to 2 records instead.
This is what is happening under the hood:
Since you are fetching only one record, currentSelectedTeams[0] is actually returning the fixturematchday column, which it looks like is of type long and you are unable to access the attribute from it.
Another option would be to use the pretty powerful Django ORM to fetch this query result
EDIT:
If you really want to stick with cursor based implementation, try this:
cursor.execute("select f.fixturematchday, u.teamselection1or2, u.teamselectionid,u.user_id from straightred_fixture f, straightred_userselection u where u.user_id = 349 and f.fixtureid = u.fixtureid and f.fixturematchday=6 order by u.teamselection1or2 LIMIT 2")
#Note the LIMIT 2
currentSelectedTeams = cursor.fetchall()
if not currentSelectedTeams:
currentSelectedTeam1 = 0
currentSelectedTeam2 = 0
else:
currentSelectedTeam1 = currentSelectedTeams[0].teamselectionid
currentSelectedTeam2 = currentSelectedTeams[1].teamselectionid
Note that, in an edge case scenario, where only one row is returned, this implementation would fail. (You need to check for the cursor return length, etc.. )
If this were a django queryset implementation, it would look something like this:
qs = Fixture.objects.filter(..).values("fixturematchday", "userselection__ teamselection1or2", "userselection__teamselectionid", "userselection__userid")[:2]
Related
Consider a table users of 6 rows
+_______________________+
| userid | name |
+-----------------------+
| 1 | john |
| 2 | steve |
| 3 | joe |
| 4 | jason |
| 5 | abraham |
| 6 | leonard |
+-----------------------+
I am using the below SQL query:
SELECT userid,name FROM users where userid IN (2,3,4,5);
which returns 4 rows -
| 2 | steve |
| 3 | joe |
| 4 | jason |
| 5 | abraham |
Pymysql equivalent code is as below:
def get_username(user_ids):
data=[]
conn = init_db()
cur = conn.cursor(pymysql.cursors.DictCursor)
cur.executemany("SELECT userid,name from users WHERE userid IN (%s)",user_ids)
rows=cur.fetchall()
for row in rows:
data.append([row['userid'],row['name']])
cur.close()
conn.close()
return data
user_ids=[2,3,4,5]
get_usernames(user_ids)
This code just returns the last row [[5,abraham]] . How can I fetch all those rows?.
That's the (partly documented) behaviour of .executemany():
Help on method executemany in module pymysql.cursors:
executemany(self, query, args) method of pymysql.cursors.Cursor instance
Run several data against one query
:param query: query to execute on server
:param args: Sequence of sequences or mappings. It is used as parameter.
:return: Number of rows affected, if any.
This method improves performance on multiple-row INSERT and
REPLACE. Otherwise it is equivalent to looping over args with
execute().
So what you want here is cursor.execute() - but then, you have a bit more work to build your SQL query:
user_ids = (2, 3, 4, 5)
placeholders = ", ".join(["%s"] * len(user_ids))
sql = "SELECT userid,name from users WHERE userid IN ({})".format(placeholders)
cursor.execute(sql, user_ids)
data = list(cursor)
Note that cursors are iterables, so you don't need to explicitely call cursor.fetchall() then iterate on the result, you can iterate directly on the cursor. Also note that if you want a list of (id, name) tuples, using a DictCursor is just a double waste of CPU cycles (once for building the dicts and once for rebuilding tuples out of them), you could just use a default cursor and return list(cursor) instead.
My first guess is that is something related SELECT statement.
May you try this way of generating the query?
def get_username(user_ids):
data=[]
conn = init_db()
cur = conn.cursor(pymysql.cursors.DictCursor)
cur.executemany("SELECT userid,name from users WHERE userid IN "+"("+','.join(str(e) for e in user_ids)+")")
rows=cur.fetchall()
for row in rows:
data.append([row['userid'],row['name']])
cur.close()
conn.close()
return data
user_ids=[2,3,4,5]
get_usernames(user_ids)
I am new to Python and am currently trying to create a Web-form to edit customer data. The user selects a customer and gets all DSL-Products linked to the customer. What I am now trying is to get the maximum downstream possible for a customer. So when the customer got DSL1, DSL3 and DSL3 then his MaxDownstream is 550. Sorry for my poor english skills.
Here is the structure of my tables..
Customer_has_product:
Customer_idCustomer | Product_idProduct
----------------------------
1 | 1
1 | 3
1 | 4
2 | 5
3 | 3
Customer:
idCustomer | MaxDownstream
----------------------------
1 |
2 |
3 |
Product:
idProduct | Name | downstream
-------------------------------------------------
1 | DSL1 | 50
2 | DSL2 | 100
3 | DSL3 | 550
4 | DSL4 | 400
5 | DSL5 | 1000
And the code i've got so far:
db_session = Session(db_engine)
customer_object = db_session.query(Customer).filter_by(
idCustomer=productform.Customer.data.idCustomer
).first()
productlist = request.form.getlist("DSLPRODUCTS_PRIVATE")
oldproducts = db_session.query(Customer_has_product.Product_idProduct).filter_by(
Customer_idCustomer=customer_object.idCustomer)
id_list_delete = list(set([r for r, in oldproducts]) - set(productlist))
for delid in id_list_delete:
db_session.query(Customer_has_product).filter_by(Customer_idCustomer=customer_object.idCustomer,
Product_idProduct=delid).delete()
db_session.commit()
for product in productlist:
if db_session.query(Customer_has_product).filter_by(
Customer_idCustomer=customer_object.idCustomer,
Product_idProduct=product
).first() is not None:
continue
else:
product_link_to_add = Customer_has_product(
Customer_idCustomer=productform.Customer.data.idCustomer,
Product_idProduct=product
)
db_session.add(product_link_to_add)
db_session.commit()
What you want to do is JOIN the tables onto each other. All relational database engines support joins, as does SQLAlchemy.
So how do you do that in SQLAlchemy?
You have two options, really. One is to use the Query builder of SQLAlchemy's ORM, the other is using SQLAlchemy Core (upon which the ORM is built) directly. I really prefer the later, because it maps more directly to SELECT statements, but I'm going to show both.
Using SQLAlchemy Core
How to do a join in Core is documented here. First argument is the table to JOIN to, second argument is the JOIN-condition.
from sqlalchemy import select, func
query = select(
[
Customer.idCustomer,
func.max(Product.downstream),
]
).select_from(
Customer.__table__
.join(Customer_has_product.__table__,
Customer_has_product.Customer_idCustomer ==
Customer.idCustomer)
.join(Product.__table__,
Product.idProduct == Customer_has_product.Product_idProduct)
).group_by(
Customer.idCustomer
)
# Now we can execute the built query on the database.
result = db_session.execute(query).fetchall()
print(result) # Should now give you the correct result.
Using SQLAlchemy ORM
To simplify this it's best to declare some [relationships on your models][2].joinis documented [here][2]. First argument tojoin` is the model to join onto and the second argument is the JOIN-condition again.
Without the relationships you'll have to do it like this.
result = (db_session
.query(Customer.idCustomer, func.max(Product.downstream))
.join(Customer_has_product,
Customer_has_product.Customer_idCustomer ==
Customer.idCustomer)
.join(Product,
Product.idProduct == Customer_has_product.Product_idProduct)
.group_by(Customer.idCustomer)
).all()
print(result)
This should be enough to get the idea on how to do this.
I have table that is holding some data about users. There are two fields there like and smile. I need to get data from table, grouped by user_id that will show if user has likes or smiles. Query that I would write in SQL looks like:
select sum(smile) > 0 as has_smile,
sum(like) > 0 as has_like,
user_id
from ratings
group by user_id.
This would provide output like:
| has_smile | has_like | user_id |
+-----------+----------+---------+
| 1 | 0 | 1 |
| 1 | 1 | 2 |
Is there any chance this query can be translated to SQLAlchemy (Flask-SQLAlchemy to be precise)? I know there is db.func.sum but I don't know how to add comparison there, and to have label. What I did for now is:
cls.query.with_entities("user_id").group_by(user_id).\
add_columns(db.func.sum(cls.smile).label("has_smile"),
db.func.sum(cls.like).label("has_like")).all()
but that will return exact number of smiles/likes instead of just 1/0 if there is or there is not smile/like.
Thanks to operator overloading you'd do comparison the way you're used to doing in Python in general:
db.func.sum(cls.smile) > 0
which produces an SQL expression object that you can then give a label to:
(db.func.sum(cls.smile) > 0).label('has_smile')
I'm fiddling around with Python and SQLite. I have a table structured like so:
PID | CID | a | b
=================
1 | 1 | ...
1 | 2 | ...
2 | 1 | ...
2 | 2 | ...
where PID is the ID of one object, and CID the id of another. Basically, a table that keeps track of the relationships between these two objects with properties (a, b, etc...) that may override those of the objects.
When I execute the following statement in python (c is a sqlite3 cursor):
results = c.execute("SELECT cid FROM test WHERE pid=?", (the_related_id,)).fetchmany()
I only get one result in the list, however, when I run the same (?) query in a sqlite browser, I get many results as expected:
SELECT cid FROM test WHERE pid=1
Whats the deal?
The number of rows to fetch per call is specified by the size parameter. If it is not given, the cursor’s arraysize determines the number of rows to be fetched.
results = c.execute("SELECT cid FROM test WHERE pid=?", (the_related_id,)).fetchmany(N)
will return N rows.
If you want to retrieve all the rows, use fetchall() function instead:
results = c.execute("SELECT cid FROM test WHERE pid=?", (the_related_id,)).fetchall()
I'm working with python2.6 and MySQLdb. I have a table with this data
+----+--------+
| id | status |
+----+--------+
| 1 | A |
| 2 | B |
| 3 | B |
+----+--------+
I want to do an mysql update like this example:
UPDATE my_table SET status = "A" where id in (1,2,3,10001);
Query OK, 2 rows affected (0.03 sec)
Rows matched: 3 Changed: 2 Warnings: 0
And I need to know if all the ids in the update exits in the database. My idea to get this information was to compare the number of items I tried to update vs the number of matched rows. In the example the numbers are 4 vs 3.
The problem is that i don't know how to get the "Matched Rows" from the cursor information. I only see this information in cursor._info = 'Rows matched: 3 Changed: 2 Warnings: 0'.
The cursor.rowcount is the number of changed rows, so =(
Thanks!
If cursor._info contains that string, then you can just extract the 3 with a regex: re.search(r'Rows matched: (\d+)', cursor._info).group(1)
Alternatively, if you are using InnoDB tables (which support transactions), you can execute two queries: first just SELECT id FROM my_table WHERE id in (1,2,3,10001) and then get cursor.rowcount which will return the number of matching rows. Then execute your update. All queries run in the same cursors are part of the same transaction, so you are guaranteed that no other process will write the database between the queries.
Sources: see http://zetcode.com/databases/mysqlpythontutorial/
The FOUND_ROWS option makes cursor.rowcount return the number of matched rows instead:
db_connection = MySQLdb.connect(
host = settings['dbHost'],
user = settings['dbUser'],
passwd = settings['dbPass'],
db = settings['dbName'],
client_flag = MySQLdb.constants.CLIENT.FOUND_ROWS
)
Docs:
http://mysql-python.sourceforge.net/MySQLdb-1.2.2/public/MySQLdb.constants.CLIENT-module.html
http://dev.mysql.com/doc/refman/5.6/en/mysql-real-connect.html
(There's a typo in the MySQLdb docs. "client_flags" should be "client_flag")