Уведомления

Группа в Telegram: @pythonsu

#1 Сен. 18, 2023 20:00:15

romario82
Зарегистрирован: 2013-04-10
Сообщения: 56
Репутация: +  2  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

Всем здравствуйте.

Есть база данных контактов с датами рождения.
Нужно получить из БД людей у которых день рождение в ближайшие 7 дней.
Формат даты в БД - год-месяц-день.
Так я получаю дельту в 7 дней.

 today = date.today()
delta = today + timedelta(days=7)
Но год у всех контактов разный.
Как реализовать запрос к БД и делать выборку контактов по дельте (today, delta) не учитывая год, а только месяц и день?
Использую sqlalchemy.

Офлайн

#2 Сен. 19, 2023 02:54:12

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9843
Репутация: +  853  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

Для каждой записи бери месяц и день, добавляй туда текущий год и потом с этой датой проделывай вычисления на попадание в срок.

Код просто выложи, где ты там не можешь добавить этот фильтр.



Офлайн

#3 Сен. 19, 2023 07:15:27

ZerG
Зарегистрирован: 2012-04-05
Сообщения: 2627
Репутация: +  61  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

и структуру бд - тоже неплохо было бы показать



Влодение рускай арфаграфией - это как владение кунг-фу: настаящие мастира не преминяют ево бес ниабхадимости

Офлайн

#4 Сен. 19, 2023 22:32:29

romario82
Зарегистрирован: 2013-04-10
Сообщения: 56
Репутация: +  2  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

Модель простая

 class DBContact(Base):
    __tablename__ = 'contacts'
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, nullable=False, index=True)
    surname = Column(String, nullable=False, index=True)
    email = Column(String, nullable=False, index=True)
    phone = Column(String, nullable=False, index=True)
    birthday = Column(String, nullable=False, index=True)
    text = Column(String, nullable=True, index=True)

Я сделал так
 current_date = datetime.now().date()
target_date = current_date + timedelta(days=7)
birthdays = session.query(DBContact).filter(
    (extract('month', DBContact.birthday) == current_date.month) &
    (extract('day', DBContact.birthday) >= current_date.day) &
    (extract('day', DBContact.birthday) <= target_date.day)
).all()
Вроде работает, но не знаю как будет вести себя на стыке месяцев.
И тут есть кто на fastapi собаку съел??? Есть вопрос.

Офлайн

#5 Сен. 19, 2023 22:48:17

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2739
Репутация: +  183  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

 birthday = Column(String, nullable=False, index=True)


Вот как я получал бы клиентов на postgres-е, но только это тебе не поможет…
 SELECT
	id, "name", surname, email, phone, birthday, "text"
FROM
	contacts
WHERE
	numrange(
		  (SELECT EXTRACT(DOY FROM CURRENT_DATE))
		, (SELECT EXTRACT(DOY FROM CURRENT_DATE))+7
	) @> EXTRACT(DOY FROM TIMESTAMP birthday)



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Сен. 20, 2023 01:05:43)

Офлайн

#6 Сен. 20, 2023 04:12:14

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9843
Репутация: +  853  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

romario82
Я сделал так
  
current_date = datetime.now().date()
target_date = current_date + timedelta(days=7)
birthdays = session.query(DBContact).filter(
    (extract('month', DBContact.birthday) == current_date.month) &
    (extract('day', DBContact.birthday) >= current_date.day) &
    (extract('day', DBContact.birthday) <= target_date.day)
).all()
Когда выделил через extract() день и месяц, подай эти значения в новую дату, формируемую через модуль datetime, с сегодняшним годом. Когда она будет сформирована, тогда ты её сравнишь с target_date через операцию сравнения больше меньше.

Вот тебе пример
  
import datetime
 
def compare_dates(date1, date2):
    if date1 < date2:
        return -1
    elif date1 == date2:
        return 0
    else:
        return 1
 
def create_date(day, month):
    out = datetime.datetime(datetime.datetime.now().year, month, day)
    return out
 
current_date = datetime.datetime.now().date()
target_date = current_date + datetime.timedelta(days=7)
birthdays = session.query(DBContact).filter(
    compare_dates(
        create_date(
            extract('day', DBContact.birthday),
            extract('month', DBContact.birthday)
        ),
        target_date
    ) <= 0
).all()
Обрати внимание, как там что импортируется в нём.

Просто ты импортируешь имена напрямую, ты думаешь, что это умно и экономит буквы, а в итоге ты ни одной функции создать не можешь из-за этого, потому что все имена заняты импортированными именами со всех модулей.

Прочитай import this, там последней строкой указано как раз про это
  
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>



Отредактировано py.user.next (Сен. 21, 2023 01:41:24)

Офлайн

#7 Сен. 20, 2023 13:52:21

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2739
Репутация: +  183  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

> Вот тебе пример

Ой.. а не проще просто циклом данные из таблицы выбирать и их с датой сравнивать?



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#8 Сен. 21, 2023 01:25:07

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9843
Репутация: +  853  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

Rodegast
Ой.. а не проще просто циклом данные из таблицы выбирать и их с датой сравнивать?
Если там миллион данных, надо их фильтрануть сначала средствами СУБД, потому что в СУБД это всё оптимизированно, все эти операции. Для этого мы и делаем этот фильтр. А так-то он нафиг не нужен.

Что касается того, нужно ли это в СУБД делать всё, то я тебе так скажу. Вот ты заострился на PostgreSQL, типа там прикольно можно всё сделать и так далее, но вот завтра поступит команда “перевести это с PostgreSQL на MySQL или там MSSQL”, вот ты что делать будешь? переписывать сотни этих выборок с одного SQL-диалекта на другой или всё-таки ты используешь такую вот ORM типа Алхимии, которая автоматически это всё переведёт в правильные инструкции просто через одну замену драйвера где-то там в настройках?

Во-первых, вся эта фигня не относится к базе данных. То есть база данных должна просто информацию хранить (непротиворечиво, целостно, оптимально и так далее). А все вот эти анализы должны выполняться снаружи базы данных.
Во-вторых, из SQL-кода ты столько не выжмешь, сколько из питон-кода. Максимум, который там достигли в этих реляционных СУБД, - это хранимые процедуры, которые считаются чуть ли не чудом света каким-то, в то время как по сути они являются просто процедурами в какой-то там древней парадигме, которая особо ничего не даёт.



Отредактировано py.user.next (Сен. 21, 2023 01:34:15)

Офлайн

#9 Сен. 21, 2023 01:31:24

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2739
Репутация: +  183  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

> Для этого мы и делаем этот фильтр. А так-то он нафиг не нужен.

Это всё верно, но только твой пример как раз в лучшем случаи упадёт, а в худшем будет по одной записи доставать и фильтровать через compare_dates.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#10 Сен. 21, 2023 01:37:09

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9843
Репутация: +  853  -
Профиль   Отправить e-mail  

Запрос к базе данных (поиск по дате)

Rodegast
Это всё верно, но только твой пример как раз в лучшем случаи упадёт, а в худшем будет по одной записи доставать и фильтровать через compare_dates.
Зато он не будет внутрь базы заносить логику, которая там быть не должно. А падает он или нет, это надо смотреть сначала. Преждевременной оптимизацией в его коде я бы не стал заниматься, судя по тому, что он делает. Сначала надо посмотреть; может, оно просто так работать будет. Если же оптимизировать, то далеко не факт, что большая часть его кода сохранится вообще. Там вообще, может, другой подход нужен изначально.



Отредактировано py.user.next (Сен. 21, 2023 01:38:02)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version