【问题标题】:Sqlalchemy + sqlite3 | create date using date() with timedelta days taken from CTE columnSqlalchemy + sqlite3 |使用 date() 创建日期,timedelta 天数取自 CTE 列
【发布时间】:2021-11-29 18:32:27
【问题描述】:

我正在尝试使用以下方法创建一个简单的日历:

with Session(DB) as session:
    
    ints = union_all(
        select(literal(1).label('num')),
        select(2),
        select(3),
        select(4),
        select(5),
        select(6),
        select(7),
        select(8),
        select(9),
        select(10),
    ).cte()

    calendar = session.execute(
        select(
            ints.c.num,
            func.DATE(func.current_date(), f'+{ints.c.num} days')
        ).select_from(ints)
    )

    for row in calendar:
        print(row)

如何从 ints.c.num 中提取原始数据类型以创建间隔字符串? 应该类似于 DATE(CURRENT_DATE, '+1 days')。我真的希望 Sqlite 能让这一切变得更容易。

标准输出:

2021-10-10 16:57:50,882 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2021-10-10 16:57:50,883 INFO sqlalchemy.engine.Engine WITH anon_1 AS 
(SELECT ? AS num UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10)
 SELECT anon_1.num, DATE(CURRENT_DATE, ?) AS "DATE_1" 
FROM anon_1
2021-10-10 16:57:50,883 INFO sqlalchemy.engine.Engine [generated in 0.00007s] (1, '+anon_1.num days')
(1, None)
(2, None)
(3, None)
(4, None)
(5, None)
(6, None)
(7, None)
(8, None)
(9, None)
(10, None)
2021-10-10 16:57:50,883 INFO sqlalchemy.engine.Engine ROLLBACK

【问题讨论】:

  • 尝试将 f'string' 包装在 SQLAlchemy text() 函数中。
  • 我试过:``` select( func.DATE(func.current_date(), text(f'+{ints.c.num} days')) ).select_from(ints) `` ` 和 ``` select( func.DATE(func.current_date(), f'+{text(ints.c.num)} days') ).select_from(ints) ``` 无济于事

标签: python sqlite sqlalchemy


【解决方案1】:

诀窍是将列转换为String 并使用+ 连接各部分,这将转换为sqlite 的|| 连接运算符。

    import sqlalchemy as sa
    ...

    calendar = select(
        ints.c.num,
        func.DATE(func.current_date(), '+' + sa.cast(ints.c.num, sa.String) + ' days')
    ).select_from(ints)

生成的SQL是

WITH anon_1 AS 
(SELECT :param_3 AS num UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10)
 SELECT anon_1.num, DATE(CURRENT_DATE, :param_1 || CAST(anon_1.num AS VARCHAR) || :param_2) AS "DATE_1" 
FROM anon_1

【讨论】:

  • 太棒了!需要注意的一点......显然这在 f-string 中不起作用,因为 sqlalchemy 现在不知道如何将其转换为 SQL
  • 我认为 + 在这种情况下被 SQLA 覆盖为 SQL 连接而不是 Python 字符串连接,因此 f 字符串没有相同的效果:也就是说,重要的是字符串被连接起来,而不是简单地产生一个看起来像结果的字符串。
  • 感谢您解决这个问题!
猜你喜欢
  • 2020-09-24
  • 2019-01-11
  • 2012-07-10
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
相关资源
最近更新 更多