Thank you for the help! Additionally, I was wondering if it would be
able to make "newest_address" an attribute on the user class, which can
then be used in a query with ".options(joinedload('newest_address'))".
My goal would be that I get an attribute that returns the newest'
address date time on normal access and is also able to be eagerly
loaded/joined in a query object. I read up in the docs and either
column_property or Correlated Subquery Relatonship Hybrid seems to be
made for this. Which one should I use?
ButAm 20.10.2013 04:41, schrieb Michael Bayer:
> On Oct 19, 2013, at 4:24 PM, Sebastian Elsner <[email protected]> wrote:
>
>> Hello,
>>
>> using the Address and User example, where the Address is connected to
>> the User via a many-to-many relationship, I want to get all users with
>> the date of their newest address. This is what I have now:
>>
>> s.query(User, s.query(func.max(Address.created)).\
>> filter(Address.users.any()).correlate(User).as_scalar()).\
>> outerjoin(User.addresses).all()
>>
>> But this is giving me all users with the newest address in the whole
>> address table. I think the error is in the subquery's filter, but I fail
>> to see how I can fix it. I am also not tied to this query, so if you
>> know a better way to get a list of all Users and their newest address
>> date, shoot!
> the format for this is the "select user rows + an aggregate of a related
> table", this format is illustrated here:
> http://docs.sqlalchemy.org/en/rel_0_8/orm/tutorial.html#using-subqueries
> where we illustrate the count of address rows per user.
>
> I see here though you have an association table in between them so that just
> has to be added to the subquery to create a row that goes across Address and
> UserAddresses, same idea though, use subquery with aggregate + group_by,
> (outer) join to that:
>
> subq = session.query(
> func.max(Address.created).label("created"),
> UserAddresses.user_id).join(UserAddresses).\
> group_by(UserAddresses.user_id).subquery()
>
> q = session.query(User, subq.c.created).outerjoin(subq)
> print q.all()
>
>
>
>
>> Here is a working example. As you can see if you run it, even Users with
>> no Addresses assigned will get the newest address date in the query.
>>
>> import datetime
>> from sqlalchemy.ext.declarative import declarative_base
>> from sqlalchemy.engine import create_engine
>> from sqlalchemy.orm.session import sessionmaker
>> from sqlalchemy.schema import Column, ForeignKey
>> from sqlalchemy.types import Integer, DateTime, String
>> from sqlalchemy.orm import relationship
>> from sqlalchemy.sql.expression import func
>>
>> Base = declarative_base()
>>
>>
>> class Address(Base):
>> __tablename__ = 'address'
>> id = Column(Integer, primary_key=True)
>> created = Column(DateTime)
>> users = relationship('User', back_populates='addresses',
>> secondary='useraddress')
>>
>> def __repr__(self):
>> return "Address: %s, %s" % (self.id, self.created)
>>
>>
>> class User(Base):
>> __tablename__ = 'user'
>> id = Column(Integer, primary_key=True)
>> name = Column(String)
>> addresses = relationship('Address', back_populates='users',
>> secondary='useraddress')
>>
>> def __repr__(self):
>> return "User: " + self.name
>>
>>
>> class UserAddresses(Base):
>> __tablename__ = 'useraddress'
>> user_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
>> address_id = Column(Integer, ForeignKey('address.id'), primary_key=True)
>>
>> engine = create_engine('sqlite://')
>> Base.metadata.create_all(engine)
>> session = sessionmaker(engine)()
>>
>> u1 = User(name="Foo")
>> u2 = User(name="Bar")
>> u1.addresses.append(Address(created=datetime.datetime.now()))
>> u1.addresses.append(Address(created=datetime.datetime.now() -
>> datetime.timedelta(days=1)))
>> session.add(u1)
>> session.add(u2)
>> session.commit()
>> print u1, u1.addresses
>> print u2, u2.addresses
>> print session.query(User, print session.query(User,
>> session.query(func.max(Address.created)).filter(Address.users.any()).correlate(User).as_scalar()).outerjoin(User.addresses).all()
>>
>> Cheers
>>
>> Sebastian
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at http://groups.google.com/group/sqlalchemy.
>> For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.