ChatGPTすごいですね!間違えたら謝ってくれます。

 こんにちは。石川さんです。ChatGPT、何でも答えてくれるので、仕事のお悩みを聞いてもらいました。

CSVファイルはデータの中にカンマが含められません

 事の発端は、今開発中のシステムでのお話です。連携用のデータの中にカンマがありまして、そのままCSVデータとして送信すると、エラーになってしまいました。ま、CSVはカンマ区切りの値ですから、カンマは何らかの処置をしてあげなければいけません。ぼくとしてはデータを「”」ダブルクォーテーションでくくるのがお好みなのですが、要望は半角カンマは全角に置き換えてください、ということでした。ORACLEからSQLを使ってデータを取出していましたので、このSQLを変更するのが楽でよさそうですね。そこで、TRANSLATEを使って置き換えることに決めました。イメージはこんな感じになります。

-- 修正前
SELECT 商品コード||','||商品名||','||単価 FROM 商品マスタ;
-- 修正後(TRANSLATEを使って半角カンマ「,」を全角カンマ「,」に置き換える)
SELECT 商品コード||','||TRANSLATE(商品名,',',',')||','||単価 FROM 商品マスタ;

そう、色々と調べて、これでうまくいくね、というときに閃きました。ChatGPTに聞いてみたら、ちゃんと教えてくれるのでしょうか。気になって聞いてみました。

Oracleで半角カンマを全角カンマに置き換える方法を教えてください。

そうするとですねぇ、ぼくが調べたTRANSLATEではく、REPLACEをおすすめしてきました。なるほど。この場合は、書き方の違いは関数名だけですね。

-- おすすめ結果
SELECT REPLACE('1,2,3,4', ',', ',') FROM dual;

そこで、次の質問です。

translateではなくreplace関数を利用する理由は何でしょうか?

そうすると、関数の違いを説明してくれて、利点を述べてくれました。その上で何と、置換対象が一つしかない場合はREPLACEの方が単純で実行速度が速くなる、と、教えてくれました。ご存知だと思いますがTRANSLATEは指定された文字列中の文字を対応させて変換してくれます。REPLACEは指定された単語を指定した単語へ変換してくれます。なので、それは本当のような気がしましたが、置換する文字が増えるなどの拡張性を考えた場合、TRANSLATEの方がいいような気がしたので、更に質問を続けます。

translateよりreplaceの方が実行速度が速いのですね。知りませんでした。本当でしょうか。そして、今後の拡張性を考慮した場合はtranslateを利用しておいた方がよいと思いますがいかがでしょうか?

この質問に対する回答では、拡張があるならTRANSLATE使ってね、と言ってもらいました。ただ、先程の質問を繰り返したような感じだったせいか、同じような回答でした。さらに、具体的にどれくらい速いのか知りたくなって聞いてみました。

では、translateとreplaceの速度の違いはどれくらいあるのでしょうか?

こんな無茶ぶりでもちゃんと答えてくれました。テーブルを作ってランダムなデータを1万件投入してUPDATEで更新した様子と、その実測した結果を示してきました。ワオ!

  • TRANSLATE関数を使用した場合: 2.9秒
  • REPLACE関数を使用した場合: 0.6秒

いや~、これはすごいですね!ちょっと感動しました。お礼を述べて一旦終了したのですけど、、、そんなに違うかなぁ、、と思い、自分でも実測してみることにしました。1万件のデータを作って、半角の3を全角の3に置き換えて、3333を取り出す、というのを実験してみました!

-- まずはTRANSLATE
with s(n) as (
select 1 n from dual
union all
select n + 1 from s where s.n < 10000
)
select * from s
where translate(to_char(n),'3','3') = '3333';

-- 次にREPLACE
with s(n) as (
select 1 n from dual
union all
select n + 1 from s where s.n < 10000
)
select * from s
where replace(to_char(n),'3','3') = '3333';

--【実測します!】--
SQL> with s(n) as (
  2  select 1 n from dual
  3  union all
  4  select n + 1 from s where s.n < 10000
  5  )
  6  select * from s
  7  where translate(to_char(n),'3','3') = '3333';

         N
----------
      3333

経過: 00:00:00.15
SQL> with s(n) as (
  2  select 1 n from dual
  3  union all
  4  select n + 1 from s where s.n < 10000
  5  )
  6  select * from s
  7  where replace(to_char(n),'3','3') = '3333';

         N
----------
      3333

経過: 00:00:00.15
SQL>

結果が出ました。どちらも0.15秒です!やはり、2.9秒は怪しいと思いました。(笑)

1回目より2回目の方の実行速度が速くなるのはOracleがバッファキャッシュを利用しているのでよくある話なのかも、と、いうことで、再度質問してみました。

ちょっと気になったので再度質問します。先程の実行結果はtranslateよりreplaceを先に実行した場合、結果が変わってくるということはありますでしょうか?

そうすると、少々時間が経ってから「申し訳ありませんが、私の前回の回答に誤りがありました。実際には、TRANSLATE関数の方がREPLACE関数よりも実行速度が速いことが多いです。私の回答が混乱を招いてしまったこと、お詫び申し上げます。」と素直に間違いを認められました。で、ちょっと追加説明してから「再度、前回の回答が誤りであったことをお詫び申し上げます。」ですって。丁寧過ぎでしょ!

いや、感動しました。ChatGPT、すごいね!!!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


The reCAPTCHA verification period has expired. Please reload the page.