From ce84ef32244e850b755b8763d043d01d56dcc2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Wed, 18 Oct 2023 16:49:58 +0200 Subject: [PATCH] SQLAlchemy many to one and selection of the last/first child --- content/Technologie/.ztr-directory | 1 - ...23-10-18-sqlalchemy-many-to-one-queries.md | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) delete mode 100644 content/Technologie/.ztr-directory create mode 100644 content/code/2023-10-18-sqlalchemy-many-to-one-queries.md diff --git a/content/Technologie/.ztr-directory b/content/Technologie/.ztr-directory deleted file mode 100644 index 2f1101d..0000000 --- a/content/Technologie/.ztr-directory +++ /dev/null @@ -1 +0,0 @@ -{"sorting":"name-down","virtualDirectories":[]} \ No newline at end of file diff --git a/content/code/2023-10-18-sqlalchemy-many-to-one-queries.md b/content/code/2023-10-18-sqlalchemy-many-to-one-queries.md new file mode 100644 index 0000000..11b3c65 --- /dev/null +++ b/content/code/2023-10-18-sqlalchemy-many-to-one-queries.md @@ -0,0 +1,40 @@ +--- +title: Using DISTINCT in Parent-Child Relationships +headline: How to get parent and most-recent child in a one-to-many relationship +tags: SQL, SQLAlchemy, Python +--- + +Let's say you have a model defined like this, with a Parent and a Child table: + +```python + +class Parent(Base): + __tablename__ = "parent" + id: Mapped[int] = mapped_column(primary_key=True) + + childs: Mapped[List["Child"]] = relationship(back_populates="parent") + + +class Child(Base): + __tablename__ = "child" + id: Mapped[int] = mapped_column(primary_key=True) + parent_id: Mapped[int] = mapped_column(ForeignKey("parent.id")) + parent: Mapped["Parent"] = relationship(back_populates="children") + + born_at: Mapped[datetime] = mapped_column() +``` + +I've tried many ways, with complex subqueries and the like, before finding out [the DISTINCT SQL statement](https://www.sqlitetutorial.net/sqlite-distinct/). + +So, if you want to retrieve the parent with it's more recent child, you can do it like this: + +```python + +results = ( + db.query(Parent, Child) + .join(Child) + .distinct(Parent.id) + .order_by(Parent.id, desc(Child.born_at)) + .all() +) +``` \ No newline at end of file