2016-10-11 2 views
2

У меня есть таблица mysql, представляющая редакционные статьи и их метаданные, такие как название, автор и дата.Как фильтровать поле datetime +/- datetime с помощью SQLalchemy

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

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

Мой текущий запрос SQLAlchemy выглядит следующим образом:

import sqlalchemy as sa 
import models as m 

s = session() 
q = (s.query(m.Article.fb_shares, func.avg(m.ArticlesMetric.views)), 
.join(m.ArticlesMetric) 
.filter(sa.between(m.ArticlesMetric.tstamp, 
     m.Article.created + timedelta(hours=1), 
     m.Article.created + timedelta(hours=3)) 
     ) 
.group_by(m.Article.id)) 

result = q.all() 
s.close() 

Однако это приводит к следующей ошибке:

Warning: (1292, u"Truncated incorrect DOUBLE value: '1970-01-01 05:30:00'") 

MySql внутренне преобразующий различных типов в парном разряде, прежде чем сделать сравнение когда выполняется сравнение между различными типами. Я считаю, что эта ошибка как-то является результатом использования timedelta, но я не уверен, как еще я могу добиться того, что я пытаюсь сделать. Любые предложения очень приветствуются.

+0

Как вы определили столбцы 'm.Article.created' и' m.ArmetMetric.tstamp'? – julienc

+0

'created = Column (DateTime)' – vaerek

+0

А как насчет 'm.ArticlesMetric.tstamp'? – julienc

ответ

2

Собственно, это сложнее, чем кажется. Если вы сделали это в MySQL напрямую, это то, что вы написали бы:

SELECT ... 
FROM ... 
JOIN ... 
WHERE tstamp BETWEEN DATE_ADD(created, INTERVAL 1 HOUR) AND DATE_ADD(created, INTERVAL 3 HOUR) 
GROUP BY ... 

И вы должны сделать более или менее то же самое с SQLAlchemy, просто потому, что m.Article.created не является постоянной величиной.

Если включить ведение журнала запросов, вы можете увидеть запрос MySQL сгенерированный код, и посмотреть, что он не соответствует тому, что вы бы подумал:

INFO:sqlalchemy.engine.base.Engine:SELECT test.id AS test_id, test.dt AS test_dt, test.tp AS test_tp 
FROM test 
WHERE test.tp BETWEEN test.dt + %(dt_1)s AND test.dt + %(dt_2)s 
INFO:sqlalchemy.engine.base.Engine:{'dt_1': datetime.datetime(1970, 1, 1, 1, 0), 'dt_2': datetime.datetime(1970, 1, 1, 3, 0)} 

мне удалось найти способ сделать то, что вы хотите, вот код:

from sqlalchemy.sql import func 
from sqlalchemy.sql.expression import text 

... 
filter(sa.between(m.ArticlesMetric.tstamp, 
    func.date_add(m.Article.created, text('INTERVAL 1 HOUR')), 
    func.date_add(m.Article.created, text('INTERVAL 3 HOUR'))) 
Смежные вопросы