С помощью SQLAlchemy, как запросить первую запись каждый день - PullRequest
0 голосов
/ 20 мая 2018

Я буду использовать структуру таблицы на Эта страница

class Book(Base):  
    __tablename__ = "books"    
    id = Column(Integer,Sequence('book_seq'),primary_key=True) 
    name = Column(String(50))
    time_added = Column(DateTime, default=datetime.datetime.now)

Скажем, у меня есть эти книги, добавленные в таблицу:

  1. day1, 1: 00
  2. день1, 2: 00
  3. день2, 1: 00
  4. день2, 2: 00
  5. день2, 3: 00

Как сделать запрос, который отфильтровывает строки 1 и 3, в которых записывается первая книга, добавленная в тот день?

Я пытался

Book.query.order_by(Book.date_added).\
    group_by(db.func.date(Book.date_added, "start of day"))

Но на самом деле этодает последний результат каждого дня, что неправильно.И теперь я понятия не имею, что я могу сделать, потому что документ и пример sqlalchemy настолько ограничены.

Пожалуйста, помогите мне выяснить, в чем проблема, или скажите мне правильный запрос, большое спасибо.

Редактировать:
Спасибо за предложения по уточнению.

Используемый мной бэкэнд базы данных: sqlite.

А для входов и выходов проблемы:
Таблица books содержит много книг, добавленных в разное время разных дней (разные time_added).И я хочу отфильтровать книги, которые были первыми в те дни.Пусть дни будут группами, и выберите книгу с самым ранним добавлением времени в группе.

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Это довольно распространенная проблема в SQL, и у нее есть собственный тег: .В вашем случае N = 1 , что делает его немного проще в SQLite.Одним из решений является использование антисоединения или, другими словами, выбор строк, для которых не существует строки с меньшей меткой времени.Это можно реализовать с помощью левого соединения:

book_alias = aliased(Book)
Book.query.\
    outerjoin(
        book_alias,
        and_(func.date(Book.time_added) == func.date(book_alias.time_added),
             Book.time_added > book_alias.time_added)).\
    filter(book_alias.id == None).\
    all()

То же самое, используя выражение подзапроса EXISTS:

Book.query.\
    filter(not_(db.session.query(book_alias).
                filter(book_alias.time_added < Book.time_added,
                       func.date(book_alias.time_added) ==
                       func.date(Book.time_added)).
                exists())).\
    all()

Конечно, вы также можете использовать подзапрос, чтобы найти минимальные значения вгруппа и фильтр на основе этого:

sq = db.session.query(func.min(book_alias.time_added)).\
    filter(func.date(book_alias.time_added) == func.date(Book.time_added))

Book.query.\
    filter(Book.time_added == sq).\
    all()

Запросы могут выполняться по-разному в зависимости от ваших данных, поэтому проверьте, что подходит вам лучше всего.

0 голосов
/ 21 мая 2018

Вы можете использовать функцию rownumber () с условием rownumber = 1.Следуйте этому примеру: Сложный запрос (подзапросы, оконные функции) с sqlalchemy complex-query-subqueries-window-functions-with-sqlalchemy

...