Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Select Query with "as" and Join Table in SQLAlchemy ORM

I'm about to create query select join with sqlalchemy like:

SELECT position.*, device.name as devicename
FROM `position` JOIN `device`
ON position.id_device = device.id
ORDER BY position.id_device

So in python file, I create the query like the following:

result = sql.query(Position, Device).\
            join(Device, Position.id_device == Device.id).\
            order_by(Position.id_device).first()

I got the result:

[
  {
    "id": 1,
    "size": "600x300",
    "price": 150,
    "id_category": 0,
    "id_device": 1,
    "impression": 9999,
    "status": 1,
    "name": "Home Top Banner",
    "id_website": 1
  },
  {
    "deleted_at": null,
    "status": 1,
    "name": "Desktop",
    "id": 1
  }
]

The result that i want as the mysql query above is:

[
  {
    "id": 1,
    "size": "600x300",
    "price": 150,
    "id_category": 0,
    "id_device": 1,
    "impression": 9999,
    "status": 1,
    "name": "Home Top Banner",
    "id_website": 1,
    "devicename": "Desktop",
  }
]

The main code flow:

[...]
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
[...]

from sqlalchemy.orm import Session

def db_session() -> Generator:
    """
    Get database connection with DI (Dependencies Injection)
    """
    try:
        dbsession = SessionLocal()
        yield dbsession
    finally:
        dbsession.close()
    
@router.get('/{ad_type}')
def ad_unit(
        ad_type: str,
        sql: Session = Depends(db_session)
):
    """Display ads unit of the available product"""
    result = get_position(sql, ad_type=ad_type)
    return result
    [...]    

def get_position(sql: Session, ad_type: str):
    result = sql.query(Position, Device).\
              join(Device, Position.id_device == Device.id).\
              order_by(Position.id_device).first()
    [...]

Model classes:

from sqlalchemy import Column
from sqlalchemy.dialects import mysql

from app.settings.mysql_settings import Base


class Position(Base):
    """A class used to represent position table (ads price list & dimensions)"""
    __tablename__ = 'position'

    id = Column(mysql.INTEGER(display_width=11, unsigned=True), primary_key=True,
                index=True, autoincrement=True)
    id_device = Column(mysql.INTEGER(display_width=11), nullable=True)
    id_website = Column(mysql.INTEGER(display_width=11), nullable=True)
    id_category = Column(mysql.INTEGER(display_width=11), nullable=True)
    name = Column(mysql.VARCHAR(length=50, collation="utf8_unicode_ci"), nullable=True)
    price = Column(mysql.INTEGER(display_width=11), nullable=True)
    status = Column(mysql.TINYINT(display_width=1), nullable=True, default=1)
    size = Column(mysql.TEXT(collation="utf8_unicode_ci"), nullable=True)
    impression = Column(mysql.DOUBLE(), nullable=False, default=0)


class Device(Base):
    """A class used to represent a list of device type for ads unit e.g: Mobile, Desktop, etc."""
    __tablename__ = 'device'

    id = Column(mysql.INTEGER(display_width=11), primary_key=True,
                index=True, autoincrement=True)
    name = Column(mysql.VARCHAR(length=50, collation="latin1_swedish_ci"), nullable=True)
    status = Column(mysql.TINYINT(display_width=1), nullable=True, default=1)
    deleted_at = Column(mysql.TIMESTAMP(), nullable=True)

I've tried many ways to get the result that I want, by merge/union the result and others but it doesn't work. I think there's a specific way to get the result that I want with sqlalchemy but I cannot found it in the doc because there are so many references.

Any help would be appreciated, thanks.

like image 290
metaphor Avatar asked Nov 23 '25 10:11

metaphor


1 Answers

Well, I finally found the answer, I've tried so many ways and you know what print save my day :D

So, I found 2 solutions here, and both of it is work like want I want. The first one is still using the ORM style, and the second one by doing the raw query

j = join(Position, Device, Position.id_device == Device.id)
stmt = select([Position, Device.name.label('devicename')]).select_from(j)
result = sql.execute(stmt)
return result.fetchall()

# or by raw query
result = sql.execute("""SELECT position.*, device.name as devicename
    FROM `position`
    JOIN `device` on position.id_device = device.id
    ORDER BY position.id_device""")
return result.fetchall()

That's it. Thank you all for your help.

like image 182
metaphor Avatar answered Nov 25 '25 00:11

metaphor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!