python - tipos - subconsultas sql pdf
SQLAlchemy: subconsulta en una cláusula WHERE (2)
Recientemente comencé a usar SQLAlchemy y todavía tengo problemas para entender algunos de los conceptos.
Reducido a los elementos esenciales, tengo dos tablas como esta (esto es a través de Flask-SQLAlchemy):
class User(db.Model):
__tablename__ = ''users''
user_id = db.Column(db.Integer, primary_key=True)
class Posts(db.Model):
__tablename__ = ''posts''
post_id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey(''users.user_id''))
post_time = db.Column(db.DateTime)
user = db.relationship(''User'', backref=''posts'')
¿Cómo voy a consultar sobre una lista de usuarios y su publicación más reciente (excluyendo usuarios sin publicaciones)? Si estuviera usando SQL, haría:
SELECT [whatever]
FROM posts AS p
LEFT JOIN users AS u ON u.user_id = p.user_id
WHERE p.post_time = (SELECT MAX(post_time) FROM posts WHERE user_id = u.user_id)
Así que sé exactamente el SQL "deseado" para obtener el efecto que quiero, pero no tengo idea de cómo expresarlo "correctamente" en SQLAlchemy.
Editar: en caso de que sea importante, estoy en SQLAlchemy 0.6.6.
Esto debería funcionar (SQL diferente, el mismo resultado):
t = Session.query(
Posts.user_id,
func.max(Posts.post_time).label(''max_post_time''),
).group_by(Posts.user_id).subquery(''t'')
query = Session.query(User, Posts).filter(and_(
User.user_id == Posts.user_id,
User.user_id == t.c.user_id,
Posts.post_time == t.c.max_post_time,
))
for user, post in query:
print user.user_id, post.post_id
la respuesta anterior funciona, pero también el sql exacto que solicitó está escrito de forma similar a la declaración real:
print s.query(Posts)./
outerjoin(Posts.user)./
filter(Posts.post_time==/
s.query(
func.max(Posts.post_time)
).
filter(Posts.user_id==User.user_id).
correlate(User).
as_scalar()
)
Supongo que el "concepto" que no es necesariamente aparente es que as_scalar () es actualmente necesario para establecer una subconsulta como un "escalar" (probablemente debería suponer que del contexto contra ==).
Editar: confirmado, es un comportamiento con errores, ticket completado # 2190. En la sugerencia o versión actual 0.7.2, se llama automáticamente a as_scalar () y la consulta anterior puede ser:
print s.query(Posts)./
outerjoin(Posts.user)./
filter(Posts.post_time==/
s.query(
func.max(Posts.post_time)
).
filter(Posts.user_id==User.user_id).
correlate(User)
)