Я пытаюсь вычесть результаты двух разных вызовов select
в SQLAlchemy как еще один select
, чтобы, наконец, вызвать order_by
для воссоздания следующего запроса:
SELECT reviews.id FROM reviews
ORDER BY (
SELECT (
SELECT COUNT(*) FROM review_upvoters WHERE review_id = reviews.id
) - (
SELECT COUNT(*) FROM review_downvoters WHERE review_id = reviews.id
)
);
Я пытался просто вычесть два выбора друг из друга (query_one - query_two
), два безрезультатно и просмотреть документы SQLAlchemy, но они точно не помогли.
В настоящее время у меня есть следующее:
upvoters_count = select([func.count()]).where(ReviewUpvoters.review_id == Review.id)
downvoters_count = select([func.count()]).where(ReviewDownvoters.review_id == Review.id)
reviews = Reviews.query.order_by(...)
где я пытаюсь выяснить внутреннюю часть order_by
, чтобы правильно вычесть эти select
s.
(Если Reviews.query
выглядит странно, это потому, что я использую Gino для асинхронной поддержки Postgres, но по большей части он использует обычные объекты SQLAlchemy, поэтому это не должно ни на что влиять.)
Поскольку __sub__
, похоже, не определен для Select
объектов, я немного озадачен этим, и я не на 100% заинтересован в реструктуризации таблиц, чтобы эти две таблицы находились в одной таблице с чем-то, чтобы их различать.
@Tryph сладкий, кажется, работает отлично.
Почему бы немного не реорганизовать этот запрос? Я думаю, что это было бы быстрее, и это определенно упростило бы то, что вы должны просить sqlalchemy сделать.
SELECT reviews.id
FROM reviews
LEFT JOIN review_upvoters ON reviews.id = review_upvoters.review_id
LEFT JOIN review_downvoters ON reviews.id = review_downvoters.review_id
GROUP BY reviews.id
ORDER BY
COUNT(DISTINCT review_upvoters.id) - COUNT(DISTINCT review_downvoters.id)
;
Судя по моему тестированию, это не дает того же результата, что и исходный запрос gist.github.com/Ovyerus/dfe1a49966fed5b982d3d7417f63939e.
Я считаю, что вам понадобится COUNT (DISTINCT), так как происходит два соединения
Благодаря @Tryph я заработал, используя as_scalar()
в подзапросах.
upvoters_count = select([func.count()]).where(ReviewUpvoters.review_id == Review.id).as_scalar()
downvoters_count = select([func.count()]).where(ReviewDownvoters.review_id == Review.id).as_scalar()
query = Reviews.query.order_by(upvoters_count - downvoters_count)
который производит следующий запрос, который сопоставим с моим исходным
SELECT reviews.id, reviews.created_at, reviews.rating, reviews.content, reviews.title, reviews.mod_id, reviews.author_id
FROM reviews
ORDER BY (
SELECT count(*) AS count_1
FROM review_upvoters
WHERE review_upvoters.review_id = reviews.id
) - (
SELECT count(*) AS count_2
FROM review_downvoters
WHERE review_downvoters.review_id = reviews.id
);
не уверен в этом: попробуйте
Reviews.query.order_by(upvoters_count.as_scalar() - downvoters_count.as_scalar())
docs.sqlalchemy.org/en/latest/core/…