如何在sqlalchemy中使用函数 - SQL Server的CAST(日期时间为日期)?

时间:2015-09-30 12:05:41

标签: python sql-server sqlalchemy

我有一个包含列的表格 - id(int)date(DateTime)value(float)。我想按日期输出具有id=2.

的所有行的日平均值

我为此编写了以下sql查询,并且查询工作正常:

select cast(date as date), avg(value) from table where id=2 group by cast(date as date)

对于同样的问题,如果我想在sqlalchemy中执行,我使用了以下表达式:

>> from sqlalchemy import sql, types
>> x = sql.cast(Table.date, types.Date)

但是当我尝试执行x时,我遇到了以下错误:

>> x.execute()    
ArgumentError: Not an executable clause: CAST(Table.date AS DATETIME)

这意味着SQL Server正在考虑types.Date as DateTime。 请忽略ArgumentError。我要关注的是内部SQL查询使用CAST(Table.date AS DATETIME)而不是CAST(Table.date AS DATE) 有没有办法让我可以在sqlalchemy中将DateTime转换为Date?

1 个答案:

答案 0 :(得分:0)

以下代码错误:

  1. 您无法执行clause。您需要有一个声明或查询(见下文)。这就是您最初错误的原因。
  2. 的确,如果你转向sa.Datemssql引擎将转为DATETIME。我不完全确定为什么会这样,但我怀疑是因为旧版本的MSSQL没有单独的DATE - 仅数据类型。要解决此问题,请将其简单地转换为DATE方言中的mssql数据类型。
  3. 以下代码应该有效。我现在没有mssql,但我确实显示了mssql的SQL语句的汇编:

    from sqlalchemy import create_engine, Column, Integer, Float, Date, DateTime, func
    from sqlalchemy.dialects.mssql import DATE
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy.ext.declarative import declarative_base
    
    # @TODO: replace with your connection string
    engine = create_engine('sqlite:///:memory:', echo=True)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    Base = declarative_base()
    
    
    class MyTable(Base):
        __tablename__ = 'my_table'
        id = Column(Integer, primary_key=True)
        date = Column(DateTime())
        value = Column(Float())
    
    Base.metadata.create_all(engine)
    
    def get_mssql_sql(qry):
        from sqlalchemy.dialects import mssql
        dialect = mssql.dialect()
        return str(qry.compile(dialect=dialect))
    
    
    # DATE = Date  # @note: this will not work in MSSQL (shows problem-2)
    q = (session
         .query(func.cast(MyTable.date, DATE), func.avg(MyTable.value))
         .filter(MyTable.id == 2)
         .group_by(func.cast(MyTable.date, DATE))
         )
    print(get_mssql_sql(q.statement))
    
    # in your code, just run below to execute:
    rows = q.all()