【问题标题】:Snowflake write_pandas is not inserting dates correctly雪花 write_pandas 未正确插入日期
【发布时间】:2021-06-14 06:41:08
【问题描述】:

我有一个名为“df”的 pandas 数据框,我正在使用针对 Netezza 数据库的 SQL 查询结果创建该数据框。我在 Jupyter 笔记本上工作。数据框有两行,其中两列(CREATEDDATE 和 STAGEDATE)包含日期时间值。当我运行 print(df) 时,结果如下所示:

                   ID ISDELETED            PARENTID         CREATEDBYID  \
0  017o000003tQRftAAG     false  a0no000000Hrv1IAAR  005o0000001w8wgAAA   
1  017o000003jl52cAAA     false  a0no000000GszDUAAZ  005o0000001w2pTAAQ   

          CREATEDDATE    FIELD OLDVALUE NEWVALUE  STAGEDATE  
0 2015-07-30 14:51:41  created     None     None 2016-06-06  
1 2015-07-16 14:48:37  created     None     None 2016-06-06

如果我运行 print(df.dtypes),结果是这样的:

ID                     object
ISDELETED              object
PARENTID               object
CREATEDBYID            object
CREATEDDATE    datetime64[ns]
FIELD                  object
OLDVALUE               object
NEWVALUE               object
STAGEDATE      datetime64[ns]
dtype: object

所以,据我所知,我的日期时间列的格式正确,可以使用 write_pandas() 写入雪花。但是,在我这样做之后,Snowflake 中的日期大不相同:

例如,2016-06-06 的 STAGEDATE 值现在是 48399-06-06。有谁知道如何解决这一问题?我正在使用 pyodbc 从 Netezza 拉取数据,并使用 df = cs.execute() 填充数据框。我正在导入和使用 snowflake.connector 连接到 Snowflake,并运行以下命令来获取 write_pandas:

from snowflake.connector.pandas_tools import write_pandas

【问题讨论】:

  • 你能分享一下 Snowflake 中目标表的结构吗?特别是两个日期列 CREATEDDATE 和 STAGEDATE 的数据类型。此外,可能值得检查 TIMESTAMP_OUTPUT_FORMAT 参数(请参阅显示参数命令docs.snowflake.com/en/sql-reference/sql/show-parameters.html
  • 创建或替换 TRANSIENT TABLE ACCT_HST (ID VARCHAR(18), ISDELETED VARCHAR(5), ACCOUNTID VARCHAR(18), CREATEDBYID VARCHAR(18), CREATEDDATE TIMESTAMP_NTZ(9), FIELD VARCHAR(255) , OLDVALUE VARCHAR(255), NEWVALUE VARCHAR(255), STAGEDATE TIMESTAMP_NTZ(9) );
  • 我的直觉是您的 TIMESTAMP_OUTPUT_FORMAT 的会话/帐户参数设置对此负责。您可以证明使用 CONVERT_TIMEZONE('UTC', CREATEDDATE) 或检查运行 SHOW PARAMETERS 的参数 TIMESTAMP_OUTPUT_FORMAT 和 TIMESTAMP_NTZ_OUTPUT_FORMAT 将日期转换为 UTC;
  • @FrancescoQuaratino,雪花是目的地。源是 Netezza 设备(IBM Pure Data)。通过其他方法加载到雪花中的日期时间很好。只有我从我的 Python 程序加载的程序有这个问题。

标签: python pandas datetime snowflake-cloud-data-platform


【解决方案1】:

我找到了使用 pday 在此处编写的代码 https://github.com/snowflakedb/snowflake-connector-python/issues/319#issuecomment-764145625 的解决方案。 此函数会自动在日期类型中添加一个时区(函数中的默认时区是 UTC)。

def fix_date_cols(df, tz = 'UTC'):
cols = df.select_dtypes(include=['datetime64[ns]']).columns
for col in cols:
    df[col] = df[col].dt.tz_localize(tz)

所以我建议在将数据帧传递给 write_pandas 之前使用这个函数。

据我所知,问题是 datetime 对象被误解了,因为它的定义不够明确。添加时区信息将强制将元素解释为日期时间。

但我真的建议您阅读这篇精彩的对话,其中有很好的解释 https://github.com/snowflakedb/snowflake-connector-python/issues/319 它真的帮助了我。

【讨论】:

    【解决方案2】:
    SELECT '2016-06-06'::timestamp as a
        ,to_timestamp_ntz(date_part('epoch_second', a),0)::date as a_s
        ,to_timestamp_ntz(date_part('epoch_millisecond', a),0)::date as a_ms
        ,to_timestamp_ntz(date_part('epoch_millisecond', a),3)::date as b_ms;
    

    给予

    A                        A_S          A_MS         B_MS
    2016-06-06 00:00:00.000  2016-06-06   48399-06-06  2016-06-06
    

    也就是说,你的日期,变成了纪元毫秒并解析为秒给你的日期。

    所以你可以扔掉你的毫秒数,或者改变你的日期被解析的方式。

    【讨论】:

    • 根据 write_pandas 函数的 Snowflake 文档,Snowflake 中 TIMESTAMP_NTZ、TIMESTAMP_LTZ 和 TIMESTAMP_TZ 的 Snowflake 到 Pandas 数据映射为 pandas.Timestamp(np.datetime64[ns])。我的日期时间值已经是 datetime64[ns],所以我认为它们会起作用,但我会看看 Python 中的隐式转换是否能解决问题。
    猜你喜欢
    • 2020-01-29
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多