【问题标题】:SQLAlchemy : Convert to date typeSQLAlchemy:转换为日期类型
【发布时间】:2014-10-14 18:07:18
【问题描述】:

这是我的 mssql 代码 sn-p

Select
     Sum((Case
            When (me.status in ('CLOSED','VOID') and
            Convert(DATE,me.end_dt)=CONVERT(DATE,GETDATE()))
            Then 1 else 0
            end)) as completed,

     Sum((Case
            When datediff 
            ( hh, cast (CONVERT (DATE, GETDATE()) as varchar)+' '+ '00:00:00.000', me.due_dt)
            between 12 and 24 and me.status not in ('CLOSED','VOID')
            Then 1 else 0
            end)) as Count_12_to_24 

     from pvr_svc me with(nolock)

对于第一块查询,这是我迄今为止尝试过的。

expr = func.sum(case([(and_(pvr_svc.status.in_(['CLOSED','VOID']), 
       (func.convert(DATE, pvr_svc.end_dt)== func.convert(DATE, func.current_date()))
       ),1)],else_=0)).label('com')

session.query(expr).scalar()

但我收到一个错误提示。

****** NotImplementedError: 不知道如何对值进行文字引用(类 'sqlalchemy.types.DATE')***

我有几个问题,

第一季度。如何将 datetime 列值(在上述情况下为 me.end_dt)转换为 DATE 类型?

第二季度。 sqlalchemy 中的 GETDATE() 等价物是什么? (我试过 func.current_date(), func.now())

第三季度。实现mssql代码sn-p最后一块的正确方法是什么?

我已经通过sqlalchemy doc, 在stackoverflow上找到了一些信息,下面是链接,

convert selected datetime to date in sqlalchemy

Comparing Dates with SQLAlchemy, SQLite

【问题讨论】:

    标签: python sql sqlalchemy


    【解决方案1】:
    expr = func.sum(
        case([(and_(
            pvr_svc.status.in_(['CLOSED', 'VOID']),
            func.strftime('%Y-%m-%d', pvr_svc.end_dt) == func.date('now'),
        ), 1)], else_=0)
    ).label("com")
    

    这将只对DATE 进行字符串比较(这是您想要的),但使用YYYY-MM-DD 格式的字符串 表示,因此所有比较都将按预期进行。

    【讨论】:

    • 感谢面包车的回答。我收到一个错误*** ProgrammingError: (ProgrammingError) ('42000', 319, "[unixODBC][FreeTDS][SQL Server]Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.", 8466) "SELECT sum(CASE WHEN (pvr_svc.status IN ('CLOSED', 'VOID') AND strftime('%Y-%m-%d', pvr_svc.end_dt) = date('now')) THEN 1 ELSE 0 END) AS com \nFROM pvr_svc AS pvr_svc WITH (NOLOCK)" ()。 pvr_svc.end_dt 列几乎没有空条目。
    • 如您所见,该错误与日期比较无关,而是与WITH (NOLOCK) 语句有关。所以你应该在那里寻找问题的原因。或者,如果您也想获得关于该部分的反馈,请至少分享您添加它的代码。我写的答案是针对sqlite 数据库。并且您将需要其他 func.xxx 函数用于不同的数据库引擎。
    • 如果我删除 func.xxx 那么我不会得到任何错误。由于我要连接到 mssql db,我应该使用 sqlalchemy.dialects.mssql.DATETIME2 吗?我找不到正确的语法。
    【解决方案2】:

    这是我得到的解决方案,

    from sqlalchemy import DATE, cast
    
    expr1 = func.sum(case([(
            and_(
                (func.convert(literal_column('DATE'), pvr_svc.due_dt) == func.convert(literal_column('DATE'), func.getdate())), 
                pvr_svc.status.in_(['CLOSED','VOID'])
                ),1
            )],else_=0)).label('completed')
    
    expr2 = func.sum(case([(
        and_(
            func.datediff(literal_column('hh'), cast(func.convert(literal_column('DATE'), func.getdate()), VARCHAR)
                +" "+"00:00:00.000",pvr_svc.due_dt)
                .between(0,12),~pvr_svc.status.in_(['CLOSED','VOID'])
            ),1)],else_=0)).label('Count_0_to_12')
    
    session.query(expr1, expr2).all()
    

    或者,

    我们可以使用 cast 函数而不是 convert 函数。

    expr1 = func.sum(
               case([(and_
                 ((cast(pvr_svc.end_dt,DATE) == cast(func.getdate(),DATE)),
                   pvr_svc.status.in_(['CLOSED','VOID'])
                 ),1)],else_=0)
               ).label('com')
    
    session.query(expr1).all()
    

    cast 和 convert w.r.t to performance 之间没有区别,因为 cast 函数在内部被实现为 sql 中的 convert 函数。查找更多信息here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-28
      • 2011-12-16
      • 2021-03-02
      • 1970-01-01
      • 2014-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多