У меня есть приложение Flask, которое отображает простую статистику о количестве книг, введенных пользователем, и о том, сколько книг он помечает как прочитанное каждый месяц. При локальном тестировании запроса в базе данных SQLite3 все работает нормально. Однако, когда я выполняю развертывание на Heroku, использующем базу данных PostgreSQL, статистика получается неправильной. Запрос выглядит так:
books_group = db.session.query(extract("month", Book.timestamp), func.count(Book.id), func.count(Book.read)).filter(Book.user_id == current_user.id).group_by(extract("month", Book.timestamp)).all()
При локальном запуске вывод выглядит следующим образом: [(4, 27, 21)]
где первое число — это месяц, второе — количество введенных книг, а третье — количество прочитанных книг. При работе на Heroku вывод: [(4.0, 10, 10)]
Независимо от того, что я делаю, количество введенных книг и количество книг, помеченных как прочитанные, всегда одинаково, хотя вывод должен быть [(4.0, 10, 5)]
Моя модель выглядит так:
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
read = db.Column(db.Boolean, default=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
И данные выглядят так:
+----+--------+-----------------------+------+---------+
| id | title | timestamp | read | user_id |
+----+--------+-----------------------+------+---------+
| 1 | Foo | 17 apr. 2020 13:14:47 | 1 | 1 |
| 2 | Bar | 17 apr. 2020 13:14:47 | 1 | 1 |
| 3 | Baz | 18 apr. 2020 13:14:47 | 0 | 1 |
| 4 | Foobar | 18 apr. 2020 13:14:47 | 1 | 2 |
| 5 | BarBaz | 18 apr. 2020 13:14:47 | 0 | 2 |
| | FooBaz | 19 apr. 2020 13:14:47 | 0 | 1 |
+----+--------+-----------------------+------+---------+
Что здесь происходит не так?
РЕДАКТИРОВАТЬ:
Решение, которое работало как для SQLite3, так и для PostgreSQL:
books_group = db.session.query(extract("month", Book.timestamp), func.count(Book.id), func.sum(cast(Book.read, Integer))).filter(Book.user_id == current_user.id).group_by(extract("month", Book.timestamp)).all()
func.count(Book.read)
подсчитывает, сколько разBook.read
не равно NULL. Если ваши данные не содержат NULL, учитывается каждая строка в группе. - person Ilja Everilä   schedule 20.04.2020func.count(Book.read == True)
приводит к тем же противоречивым результатам. Он работает на SQLite3, но не на PostgreSQL. - person Stefan   schedule 20.04.2020func.count(Book.read == True)
не имеет значения. ЕслиBook.read
является логическим столбцом, тоBook.read
иBook.read == True
эквивалентны. И еслиBook.read
равно NULL, то результатBook.read == True
также равен NULL. ПосколькуCOUNT(<expression>)
подсчитывает, сколько раз выражение expression оценивается как отличное от NULL, несоответствия нет. Ваши данные в PostgreSQL, кажется, имеют нет NULL, в то время как данные в SQLite, кажется, имеют NULL. - person Ilja Everilä   schedule 20.04.2020