2017-08-01 43 views
0

我有一个正在构建的应用程序,并希望它可以移植到多个数据库,特别是MS SQL和PostgreSQL。我面临的具体问题是与datetime数据类型。SQL Alchemy datetime和数据库方言

例如,我想通过user_id获取下面的历史表和组,获取每个用户的总时间。在time_in为空的情况下,我需要获取当前的日期时间。

所以我的问题是,我需要写我的SQL Alchemy代码是特定于数据库吗?有没有办法达到以下查询的相同结果而不使用像datdiff这样的数据库特定功能?

样品查询的SQL Server而不是PostgreSQL的作品:

history_timecase = case([(History.time_in == None, func.now())], else_=History.time_in) 

user_list = db.session.query(History.user_id, func.sum(func.datediff(text('minute'), History.time_in, history_timecase)))\ 
      .group_by(History.user_id).all() 

历史表:

+----+---------+----------------+-----------------+ 
| id | user_id | time_in  | time_out  | 
+----+---------+----------------+-----------------+ 
| 11 |  2 |    | 8/1/2017 8:14 | 
| 12 |  2 |    | 8/1/2017 8:14 | 
| 13 |  2 |    | 8/1/2017 8:14 | 
| 14 |  2 |    | 8/1/2017 8:14 | 
| 15 |  2 |    | 8/1/2017 8:14 | 
| 16 |  2 |    | 8/1/2017 8:14 | 
| 17 |  11 |    | 7/31/2017 11:30 | 
| 6 |  6 | 8/1/2017 9:25 | 8/1/2017 8:06 | 
| 18 |  12 |    | 8/1/2017 9:34 | 
| 9 |  9 | 8/1/2017 9:40 | 8/1/2017 8:51 | 
| 10 |  10 | 8/1/2017 10:00 | 8/1/2017 8:55 | 
| 22 |  14 | 8/1/2017 10:00 | 8/1/2017 9:51 | 
| 23 |  14 | 8/1/2017 10:00 | 8/1/2017 9:51 | 
| 24 |  14 | 8/1/2017 10:00 | 8/1/2017 9:51 | 
| 7 |  7 | 8/1/2017 10:15 | 8/1/2017 8:37 | 
| 25 |  14 | 8/1/2017 10:15 | 8/1/2017 10:04 | 
| 27 |  14 | 8/1/2017 10:15 | 8/1/2017 10:05 | 
| 28 |  14 | 8/1/2017 10:15 | 8/1/2017 10:05 | 
| 29 |  12 | 8/1/2017 10:15 | 8/1/2017 10:06 | 
| 26 |  15 | 8/1/2017 10:45 | 8/1/2017 10:05 | 
| 33 |  16 | 8/1/2017 11:15 | 8/1/2017 10:24 | 
| 37 |  18 |    | 8/1/2017 11:19 | 
| 34 |  17 | 8/1/2017 11:35 | 8/1/2017 10:38 | 
| 30 |  14 | 8/1/2017 11:40 | 8/1/2017 10:18 | 
| 31 |  14 | 8/1/2017 11:40 | 8/1/2017 10:18 | 
| 32 |  14 | 8/1/2017 11:40 | 8/1/2017 10:18 | 
+----+---------+----------------+-----------------+ 
+0

是的,因为'datediff'是特定于SQL Server。 – univerio

+0

我知道datediff是特定于SQL Server的。我想知道是否有另一种方法来实现我在使用数据库特定功能后的结果。 – ians

+0

您可以尝试将尽可能多的数据库特定代码封装到[自定义编译构造](http://docs.sqlalchemy.org/en/latest/core/compiler.html#further-examples)。表面上你会提供一个用于某些计算的DB不可知构造,它将在底层编译为DB特定的实现。 –

回答

0

DATEDIFF()是过于具体的SQL Server。

我张贴了建议的解决方案,其中他用的是自定义的时间间隔减去功能的Postgres的链接:

https://groups.google.com/forum/#!topic/sqlalchemy/6mSpNTMjUGU

from sqlalchemy import func 
    from sqlalchemy.sql.expression import FunctionElement 
    from sqlalchemy.ext.compiler import compiles 

    class subtract_interval(FunctionElement): 
     type = Date() 
     name = 'subtract_interval' 

    @compiles(subtract_interval) 
    def compile_subtract_interval(element, compiler, **kwargs): 
     return '(%s::date - %s::interval)' % (
      compiler.process(element.clauses.clauses[0]), 
      compiler.process(element.clauses.clauses[1]), 
    ) 

    res = session.query(Foo).filter(
     Foo.date < subtract_interval(func.now(), '3 years') 
).all()