0

文字列として保存されている日付を日付に変換しようとしています。

YYYYMMDD(文字列)~YYYY-MM-DD(日付)

私の知る限り、入力形式と出力形式をチェックする変換関数はありません。手動ロジックを試してみました。

CASE 
  WHEN CHAR_LENGTH(TRIM(some_string_date)) = 8
  THEN
    CAST(
      SUBSTRING(TRIM(some_string_date) FROM 1 FOR 4)
      || '-'
      || SUBSTRING(TRIM(some_string_date) FROM 5 FOR 2)
      ||'-'
      || SUBSTRING(TRIM(some_string_date) FROM 7 FOR 2)
    as DATE) 
  ELSE
    NULL 
END

しかし、これは Apache SQL Validator によって受け入れられません。

4

2 に答える 2

2

質問に直接答えているわけではありませんが、関連しているかもしれませんが、日付リテラルはキーワードで宣言DATEいます。

アップデート:

起こるように思われるのは、 を実行するときに Calcite がいくつかの間接性を追加することCASEです。文字列を日付にキャストすると、通常は期待どおりに機能します。たとえば、入力行にスキーマ(INT f_int, VARCHAR f_string)があり、日付が含まれている場合'YYYYMMDD'(たとえば(1, '2018')、これは機能します。

SELECT f_int,
   CAST(
    SUBSTRING(TRIM(f_string) FROM 1 FOR 4)
      ||'-'
      ||SUBSTRING(TRIM(f_string) FROM 5 FOR 2)
      ||'-'
      ||SUBSTRING(TRIM(f_string) FROM 7 FOR 2) as DATE)
  FROM PCOLLECTION

作品を直接キャストしても'YYYYMMDD'

SELECT f_int,
   CAST(f_string AS DATE)
FROM PCOLLECTION

サポートされているすべての日付形式は、こちらで確認できます。

しかし、それを でラップするとすぐに'CASE ... ELSE NULL'、Beam/Calcite は式の型が'String'. これは、 'THEN CAST(... AS DATE)'が成功して 'Date' を返すことを意味しますが、'String'にラップされると に変換され'CASE'ます。次に、テストで結果を返すときに、それを にキャストしようとしているように見え'Date'ますが、文字列形式は現在ではなく'YYYYMMDD'、他のデフォルト形式です。残念ながら、その形式はサポートされているリストにないため、失敗します。

回避策:

'ELSE NULL'であることが知られているものに変更するとすぐに'Date'、たとえば、ビーム/方解石がパス'ELSE DATE "2001-01-01"'を通過していないように見えるため、再び機能し、これが機能します。'String'->'Date'->'String'->'Date'

SELECT f_int,
  CASE WHEN CHAR_LENGTH(TRIM(f_string)) = 8
    THEN CAST (
       SUBSTRING(TRIM(f_string) FROM 1 FOR 4)
       ||'-'
       ||SUBSTRING(TRIM(f_string) FROM 5 FOR 2)
       ||'-'
       ||SUBSTRING(TRIM(f_string) FROM 7 FOR 2) AS DATE)
    ELSE DATE '2001-01-01'
  END
FROM PCOLLECTION

より良い解決策を追跡するために、BEAM-5789を提出しました。

更新 2:

したがって、Calcite は Beam に何をすべきかを伝える計画を生成しますが、この場合、実際に日付をキャスト/解析するのは Beam です。Beam ですべてを再実装する代わりに、基本的な操作の Calcite の組み込み実装を使用する試みがあります: https://github.com/apache/beam/pull/6417。このプル リクエストがマージされた後、このCASE ... ELSE NULLパスを正しく読んでいれば、このパスは自動的に機能するはずです (このクラスは日付/時刻値の処理に使用されると想定しています)。おそらく不必要に文字列を通過しますが、うまくいくはずです。

于 2018-10-18T16:40:28.110 に答える