I am trying to port the following query to SQLAlchemy:
SELECT u.username, GROUP_CONCAT(DISTINCT userS.name) FROM Skills AS filterS INNER JOIN UserSkills AS ufs ON filterS.id = ufs.skill_id INNER JOIN Users AS u ON ufs.user_id = u.id INNER JOIN UserSkills AS us ON u.id = us.user_id INNER JOIN Skills AS userS ON us.skill_id = userS.id WHERE filterS.name IN ('C#', 'SQL') GROUP BY u.id;
I don't understand how to achieve AS statement in SQLAlchemy. Here is what I currently have:
# User class has attribute skills, that points to class UserSkill # UserSkill class has attribute skill, that points to class Skill db.session.query(User.id, User.username, func.group_concat(Skill.name).label('skills')).\ join(User.skills).\ join(UserSkill.skill).filter(Skill.id.in_(skillIds)).\ order_by(desc(func.count(Skill.id))).\ group_by(User.id).all()
Please help.
Python Flask and SQLAlchemy ORM Effect of joining is achieved by just placing two tables in either the columns clause or the where clause of the select() construct. Now we use the join() and outerjoin() methods. The join() method returns a join object from one table object to another.
You use a single table twice in a query by giving it two names, like that. The aliases are often introduced with the keyword AS. You also normally specify a join condition (for without it, you get the Cartesian Product of the table joined with itself). For preference you use the explicit JOIN notation.
The self-join is a special kind of joins that allow you to join a table to itself using either LEFT JOIN or INNER JOIN clause. You use self-join to create a result set that joins the rows with the other rows within the same table.
The following example shows how to concatenate three different columns: (SELECT id, email1 AS email FROM customer) UNION (SELECT id, email2 AS email FROM customer) UNION (SELECT id, email3 AS email FROM customer) ORDER BY id, email; As you can see, it's important that all the queries return the same columns.
I figured this out. Here are the classes that are used in my Flask app:
class User(Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = Column(db.String(80), unique=True, nullable=False) skills = db.relationship('UserSkill') class Skill(Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = Column(db.String(80)) class UserSkill(Model): status = db.Column(db.Enum(SkillStatus)) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) skill_id = db.Column(db.Integer, db.ForeignKey('skills.id'), primary_key=True) skill = db.relationship("Skill")
So, the actual code would look like this:
from sqlalchemy.orm import aliased userSkillF = aliased(UserSkill) userSkillI = aliased(UserSkill) skillF = aliased(Skill) skillI = aliased(Skill) db.session.query(User.id, User.username,\ func.group_concat(func.distinct(skillF.name)).label('skills'),\ func.group_concat(func.distinct(skillI.name)).label('other_skills')).\ join(userSkillF, User.skills).\ join(userSkillI, User.skills).\ join(skillF, userSkillF.skill).filter(skillF.id.in_(skillIds)).\ join(skillI, userSkillI.skill).\ group_by(User.id).all()
Many thanks Ilja Everilä, fresh look on SqlAlchemy docs made me understand aliased
now.
We can do the join without relationships as well. Explicitly mention the condition on join.
Example
from sqlalchemy.orm import aliased user1 = aliased(UserSkill) user2 = aliased(UserSkill) query_result = db.session.query( func.distinct(User.id).label('user_id'), User.username, ).join( user1, User.id == user1.user_id, ).join( user2, user2.id == User.id, ).filter( user1.user_id == id, ).all()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With