首页 > 解决方案 > 将python日期列表传递给sql查询where子句

问题描述

我在数据框中有一个日期列,我将其转换为日期列表

begdtlist = df["BEG_DT"].tolist()

print(begdtlist)返回以下。

Timestamp('2018-04-29 00:00:00'), Timestamp('2018-04-22 00:00:00'), 
Timestamp('2018-04-22 00:00:00'), Timestamp('2018-04-29 00:00:00'), 
Timestamp('2018-04-29 00:00:00'). 

日期将类型转换为时间戳。

我将此列表传递给 SQL 查询,如下所示

sql = ("select  calndr_dt,wk_of_mnth from DatabaseName where calndr_dt = cast {} as date").format(repr(begdtlist).replace('[','(').replace(']',')'))

但是,我的 sql 是以以下格式生成的,这导致查询失败。

"select  calndr_dt,wk_of_mnth from DatabaseName where calndr_dt = cast 
(Timestamp('2018-04-29 00:00:00'), Timestamp('2018-04-22 00:00:00'), 
Timestamp('2018-04-22 00:00:00'), Timestamp('2018-04-29 00:00:00'), 
Timestamp('2018-04-29 00:00:00')) as date"

我不确定为什么它会以时间戳的形式出现。我只需要引号中的日期部分。任何实现这一目标的指导将不胜感激。

标签: pythonsqltimestamp

解决方案


您正在repr()将对象转换为字符串。此方法不适用于您应用它的用例;它提供了有关底层对象的内部表示的信息。

您真正想要做的是格式化您的时间戳,使其成为适合您需求的字符串。就像普通的 pythonDatetime对象一样,pandas'Timestamp对象也有一个strftime()用于字符串格式化的方法。

# This part is just to create a MWE; it mimics your dataframe that we
# do not have at hand here.
df = pandas.DataFrame({
    'BEG_DT': [
        pandas.Timestamp('2018-04-29'),
        pandas.Timestamp('2019-04-22')]
    })

# This is what you did
begdtlist = df['BEG_DT'].tolist()
print(begdtlist)

# This is how you can format the date according to your needs
for dt in begdtlist:
    print(dt.strftime('%Y-%m-%d'))

这会生成以下输出:

[Timestamp('2018-04-29 00:00:00'), Timestamp('2019-04-22 00:00:00')]
2018-04-29
2019-04-22

您会在第 2 行和第 3 行中看到格式化创建了生成 SQL 查询所需的日期字符串。您可以阅读官方 python 文档中的格式化选项

顺便说一句,pandas将您的日期转换为自己的Timestamp对象是完全可以的,因为它们需要用于DataFrame交互和聚合等的接口,而这些接口在常规 pythonDateDatetime对象中不存在。

不过,您不能在 SQL 查询中使用该列表,因为它会生成无效的语法:

SELECT calndr_dt, wk_of_mnth
FROM databasename
WHERE calendr_dt = CAST 2018-04-29, 2018-04-22 AS DATE
                                  ^
                    this will be your syntax error

您的方法在几个方面存在缺陷:

  1. 您正在尝试将列表插入到单个CAST调用中,这将失败
  2. 您正在测试列与数组的相等性,这将失败

因此,在尝试通过 python 插入值之前,您可能还想阅读 SQL 语法并生成示例查询。

可能看起来像这样(未经测试 - 谨慎使用):

sql = '''
    SELECT calndr_dt, wk_of_mnth
    FROM databasename
    WHERE calendr_dt IN [{:s}]
'''.format(', '.join(
    [
        '\'{:s}\'::DATE'.format(dt.strftime('%Y-%m-%d'))
        for dt in begdtlist
    ]
))

结果是:

SELECT calndr_dt, wk_of_mnth
FROM databasename
WHERE calendr_dt IN ['2018-04-29'::DATE, '2019-04-22'::DATE]

推荐阅读