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、すごいね!!!

初めてのJavaScript 読書中です

こんにちは、石川さんです。

最近、思うところがあって、JavaScriptの勉強を始めました。今読んでいるのは、そう「初めてのJavaScript 第3版」です。Angularを使い始めたので本来はTypeScriptの勉強、と言いたいところですが、一冊本を読んで、先にJavaScriptだな、という気持ちになったのでした。

いや~、JavaScript、思っていたよりも、色々とできるのですねぇ。テンプレートリテラルとか、クロージャとか、完全にPythonだけのものだと思っていたのですけど、いや、視野が狭かったですね!反省しました。

せっかく勉強しているので、色々と披露したいよねぇ、という気持ちになってきたところで気になりました。そういえばWordPressのこのページ、JavaScriptを使用できるのでしょうか。先日調べたところ、ブロックを選択すればできる、ということがどこかに書かれていましたので、ちょっと試してみましょう。

ブロックの追加

まずは、ブロックを追加します。「カスタムHTML」が選べるので、こちらを選択します。

「ブロックを追加」から「カスタムHTML」を選択

すると、以下のように「HTMLを入力…」となりますので、ここへスクリプトを記載して行きます。「プレビュー」を押すと実行結果のプレビューが表示されます。

HTMLを入力

入力して保存したところ、簡単にできました!

【1つ目】

【2つ目】

できましたね!

簡単でした♪

今回入力したスクリプトは以下の通りです。

まずは【1つ目】です。ほぼこちらのスクリプトをコピペしたものです。Konva.jsという、HTML5 2d canvasのためのJavascriptライブラリを紹介しているホームページです。
HTML要素のidがページ全体にかかわってくるので、idは、container20230303_1に変更しました。(すみません、後で気づきました。調子にのって、他の記事でもcontainerを使ったところ、一覧で見たときにかぶって変なことになってしまいました。。。)

次に【2つ目】のスクリプトです。

<style>
div#container20230303_2 {
  height: 200px;
  width: 116%;
  background-color: ivory;
}
</style>
<div id="container20230303_2"></div>
<script src="https://unpkg.com/konva@8/konva.min.js"></script>
<script>
var height = 200;
var width = window.innerWidth;
      var resourceColor = 'rgb(185, 247, 247)';
      var eventColor = 'rgb(245, 200, 247)';
      var stage = new Konva.Stage({container: 'container20230303_2', width: width, height: height, draggable:true});
      stage.on('contextmenu', function (e) {
        e.evt.preventDefault();
      });
      var layer = new Konva.Layer();
      stage.add(layer);
      function newBox(title, type) {
        return new Konva.Rect({
          cornerRadius: 10,
          fill: type === "resource" ? resourceColor : eventColor,
          stroke: 'black',
          strokeWidth: 1,
          name: 'rect',
          draggable: true,
          sceneFunc: function (context, shape) {
            shape._sceneFunc(context);
            context.beginPath();
            context.moveTo(0,20);
            context.lineTo(shape.getAttr('width'),20);
            context.moveTo(shape.getAttr('width')/2,20);
            context.lineTo(shape.getAttr('width')/2,shape.getAttr('height'));
            context.stroke();
            context.closePath();
            context.font = '12px sans-serif';
            context.fillStyle = "rgb(0, 0, 0)"
            context.fillText(title,25,17);
          }
        });
      };
      var rect1 = newBox("リソース", "resource");
      rect1.setAttrs({x: 60, y: 60, width: 100, height: 90});
      layer.add(rect1);
      var rect2 = newBox("イベント", "event");
      rect2.setAttrs({x: 260, y: 60, width: 100, height: 90});
      layer.add(rect2);
rect2.on('click', (event) => {console.log('clicked!', event);});
</script>

簡単に色々なことができるので、夢が広がりますね!