How to achieve inner join using SQLAlchemy?
For that you first need to have a session
to make a Query
. Additionally it can be convenient to have a relationship
on your MessageModel.
class MessageModel(Base):
__tablename__ = 'messages'
player_id = Column(Integer,ForeignKey('chats.id'), nullable=False)
message = Column(String(2000), nullable=False)
time = Column(TIMESTAMP, server_default=func.now())
player = relationship(PlayerModel, backref="messages")
This will create the relationship on both models.
results = (session.query(PlayerModel)
.join(PlayerModel.messages)
.values(PlayerModel.username,
MessageModel.message,
MessageModel.time))
# results will be a generator object
# This seems a bit convoluted, but here you go.
resultlist = []
for username, message, time in results:
resultlist.append({'message': message,
'username': username,
'time': time})
There may be more elegant ways to come to your data structure but this one should work.
Flask SQLAlchemy syntax for SELECT statement with inner join
filter_by()
used with keyword argument expression.
The keyword expressions are extracted from the primary entity of the query, or the last entity that was the target of a call to Query.join().
so you need write as:
productstore = ProductStore.query.filter_by(productid=3) \
.join(MyStore, ProductStore.storeid==MyStore.storeid) \
.filter_by(userid=2) \
.order_by(ProductStore.price).first()
filter()
used with SQL expression, can take field compare's result into argument.
in SQL expression you can write:
productstore = ProductStore.query.join(MyStore, ProductStore.storeid==MyStore.storeid) \
.filter(ProductStore.productid==3,
MyStore.userid ==2) \
.order_by(ProductStore.price).first()
Forcing inner join with many-to-many relationship in sqlalchemy
MySQL is doing an inner join; that is, the query you've shown is one implementation of an inner join.
From the docs:
innerjoin=False – when True, joined eager loads will use an inner join
to join against related tables instead of an outer join. The purpose
of this option is strictly one of performance, as inner joins
generally perform better than outer joins. This flag can be set to
True when the relationship references an object via many-to-one using
local foreign keys that are not nullable, or when the reference is
one-to-one or a collection that is guaranteed to have one or at least
one entry.
The key point is inner join vs. outer join. The syntax is irrelevant.
Note that your query can be converted to a query using the inner join
syntactic form which has the exact same meaning:
SELECT permissions.permissionid AS permissions_permissionid,
permissions.name AS permissions_name
FROM permissions
INNER JOIN users_permissions
ON permissions.permissionid = users_permissions.permissionid
WHERE ? = users_permissions.userid
ORDER BY permissions.name
MySQL will usually generate an identical execution plan for the two forms.
Eager Inner Join in SQLAlchemy
I might be slightly off here, but have you tried explicitly passing the join condition?
q = session.query(City.population, State.name).join(State).all()
Also, assuming your objective is the initial query, have you tried a few tweaks in the sqlalchemy
syntax to actually get the same statement?
print (q.statement)
Lastly, Query
classes have a method enable_eagerloads()
. From the docs:
Control whether or not eager joins and subqueries are rendered.
When set to False, the returned Query will not render eager joins regardless of joinedload(), subqueryload() options or mapper-level lazy='joined'/lazy='subquery' configurations.
SQLAlchemy: create sqlalchemy query from sql query with subquery and inner join
Base on your SQL I think you are trying to query the lines which user_id is given and with max date.
So first maybe we can update the SQL a little:
SELECT DISTINCT d.*, t.max_date, t.USER_ID
FROM DATABASE_ONE d
INNER JOIN (
SELECT USER_ID, MAX(DATE_CREATED) max_date
FROM DATABASE_ONE
WHERE
USER_ID IN ('1','2','3')
AND CATEGORY = 'Users'
AND IS_DELETED IS NULL
GROUP BY USER_ID
) t on t.USER_ID = d.USER_ID AND t.max_date = d.DATE_CREATED
In these case it's easier to read and convert into SQLAlchemy language.
Then the problem about your second SQLAlchemy query, is that you are trying to select from a subquery but the select is from origin table. If convert the second SQLAlchemy query into sql query, It's will look like:
SELECT DATABASE_ONE.USER_ID, MAX(DATABASE_ONE.DATE_CREATED) max_date FROM (
SELECT * FROM DATABASE_ONE
WHERE USER_ID IN ('1','2','3')
AND CATEGORY = 'Users'
AND IS_DELETED IS NULL
)
GROUP BY DATABASE_ONE.USER_ID
The better way to write the SQLAlchemy query:
subquery = Session.query(
DatabaseOne.user_id,
func.max(DatabaseOne.date_created).label("max_date"),
)
.filter(
DatabaseOne.user_id.in_('1', '2', '3'),
DatabaseOne.category == "Obligor Rating Scorecards",
DatabaseOne.is_deleted == None,
)
.group_by(DatabaseOne.user_id)
.subquery()
Session.query(
DatabaseOne, subquery.c.user_id, subquery.c.max_date # see the .c method to access column in subquery
).select_from(subquery).join(DatabaseOne).filter(DatabaseOne.user_id = subquery.c.user_id,DatabaseOne.date_created = subquery.c.max_date).all()
Related Topics
How to Access Latest Row for Each Individual Identifier
List All SQL Columns with Max Length and Greatest Length
Compare Current Row with Previous Row in SQL Server
How to Pass Schema as Parameter to a Stored Procedure in SQL Server
How to Count Unique Pairs of Values in Sql
Conditional Unique Constraint with Multiple Fields in Oracle Db
Insufficient Privileges When Creating Tables in Oracle SQL Developer
Create Geometry/Geography Field from Latitude & Longitude Fields (Sql Server)
How to Insert Distinct Records from Table a to Table B (Both Tables Have Same Structure)
Spring Data JPA - Query with The Date Minus 2 Days Not Working
Firstname, Lastname in Sql, Too Complex
Why Aren't Nulls Counted in Count(Columnname)
Passing C# Datatable as a Parameter to Stored Procedure in Ms SQL Server 2008
Orm or Something to Handle SQL Tables with an Order Column Efficiently
Ora-01779: Cannot Modify a Column Which Maps to a Non Key-Preserved Table
How to Alter a Column Datatype for Derby Database