2015-01-16 2 views
0

Что касается ответа, который я принял для этого сообщения, SQL Group By and Limit issue, мне нужно выяснить, как создать этот запрос с помощью SQLAlchemy. Для справки, запрос мне нужно запустить это:Взаимодействие между подзапросами в SQLAlchemy

SELECT t.id, t.creation_time, c.id, c.creation_time 
FROM (SELECT id, creation_time 
     FROM thread 
     ORDER BY creation_time DESC 
     LIMIT 5 
    ) t 
LEFT OUTER JOIN comment c ON c.thread_id = t.id 
WHERE 3 >= (SELECT COUNT(1) 
      FROM comment c2 
      WHERE c.thread_id = c2.thread_id 
      AND c.creation_time <= c2.creation_time 
      ) 

Я имею первую половину запроса, но я борюсь с синтаксисом предложения WHERE и как совместить его с JOIN. У кого-нибудь есть предложения?

Спасибо!

EDIT: Первая попытка, кажется, запутались вокруг вызова .filter():

c = aliased(Comment) 
c2 = aliased(Comment) 

subq = db.session.query(Thread.id).filter_by(topic_id=122098).order_by(Thread.creation_time.desc()).limit(2).offset(2).subquery('t') 

subq2 = db.session.query(func.count(1).label("count")).filter(c.id==c2.id).subquery('z') 

q = db.session.query(subq.c.id, c.id).outerjoin(c, c.thread_id==subq.c.id).filter(3 >= subq2.c.count) 

это порождает следующий SQL:

SELECT t.id AS t_id, comment_1.id AS comment_1_id 
FROM (SELECT count(1) AS count 
FROM comment AS comment_1, comment AS comment_2 
WHERE comment_1.id = comment_2.id) AS z, (SELECT thread.id AS id 
FROM thread 
WHERE thread.topic_id = :topic_id ORDER BY thread.creation_time DESC 
LIMIT 2 OFFSET 2) AS t LEFT OUTER JOIN comment AS comment_1 ON comment_1.thread_id = t.id 
WHERE z.count <= 3 

Обратите внимание на порядок суб-запрос неверен , а subq2 как-то дважды выбирает из комментария. Вручную исправление, которое дает правильные результаты, я просто не знаю, как получить SQLAlchemy, чтобы все было правильно.

ответ

1

Попробуйте это:

c = db.aliased(Comment, name='c') 
c2 = db.aliased(Comment, name='c2') 

sq = (db.session 
     .query(Thread.id, Thread.creation_time) 
     .order_by(Thread.creation_time.desc()) 
     .limit(5) 
    ).subquery(name='t') 

sq2 = (
    db.session.query(db.func.count(1)) 
    .select_from(c2) 
    .filter(c.thread_id == c2.thread_id) 
    .filter(c.creation_time <= c2.creation_time) 
    .correlate(c) 
    .as_scalar() 
) 

q = (db.session 
    .query(
     sq.c.id, sq.c.creation_time, 
     c.id, c.creation_time, 
    ) 
    .outerjoin(c, c.thread_id == sq.c.id) 
    .filter(3 >= sq2) 
    ) 
+0

Спасибо фургон, что это похоже на работу. Играя с ним, я могу получить запрос, чтобы вернуть объект Comment; есть ли способ получить вышеуказанный запрос для возврата реальных объектов модели, или это невозможно из-за подзапроса? – mrquintopolous

+0

Возможно, конечно. В конечном запросе ('q') вам нужно запросить нужный объект, а не список столбцов. В вашем случае вы можете запросить «Thread» и присоединить его к «sq», чтобы иметь одинаковое значение столбца «id». – van

Смежные вопросы