5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ユニークビジョン株式会社Advent Calendar 2023

Day 2

0から始まったり始まらなかったりするPostgreSQL

Last updated at Posted at 2023-12-01

はじめに

これはPostgreSQLを0から学ぶための入門記事ではありません。
誤解を招くタイトルで申し訳ありません。

https://qiita.com/noborus/items/5e39d144b1510f6865bd
とてもおもしろい記事でしたので、勝手にちょっと名前をもらってきました。

PostgreSQLの配列とJSON

PostgreSQLには配列型というものがあります。
基本正規化されているDBのテーブルではそう見かけることはないですが、パフォーマンスのため正規化を崩すときや、ちょっと凝ったクエリをSQLで書くときには役に立つ、なかなかに渋い奴です。

似たよう使われ方をするものにJSON型、JSONB型というものもあります。こちらは先ほどと似たような使い方をするほか、APIのレスポンスデータのような最初からJSONとして取り扱いたいデータを扱う場合に効果的です。

JSONBは表現力が高く、いろいろなJSONBを作ることができます。
以下のクエリでできるものは全部JSONBです。

-- {}
select '{}'::JSONB;
 jsonb
------
{}
(1 row)

-- 1
select '1'::JSONB;
 jsonb 
-------
1
(1 row)

select '[{"value":0}]'::JSONB;
 jsonb 
-------
[{"value": 0}]

select NULL::JSONB;
 jsonb 
-------
[NULL]

本題

以下の2つのクエリを実行したとき、返ってくる値はそれぞれなんでしょうか?

-- クエリ1
select '[{"value":0},{"value":1},{"value":2}]'::JSONB->0;
-- クエリ2
select (array[0,1,2])[0];

答えは、1つめが{"value":0}で、2つ目がNULLです。

select '[{"value":0},{"value":1},{"value":2}]'::JSONB->0;
 jsonb 
-------
{"value": 0}

select (array[0,1,2])[0];
 jsonb 
-------
[NULL]

同じPostgreSQLの中でも、配列は1始まりで、JSONの配列は0始まりなのでした。
冷静に考えると1つの言語の中でこの両方があるのはなかなかすごい言語な気がします。
ただJavaScript Object Notationに1-indexedでアクセスするのもやりたくないですし、別におかしいことはないです。ところでPostgreSQLってJSONB配列の配列も書けますよね?

select ((array['[{"value":0}]'::JSONB,'[{"value":1}]'::JSONB,'[{"value":2}]'::JSONB])[1])->0;
 jsonb 
-------
{"value": 0}

さすがに苦しい!

まとめ

SELECT FROM オチ;
--
(1 rows)

おまけ

-- JSONパスでも0始まり
select * from jsonb_path_query('[{"value":0},{"value":1},{"value":2}]'::JSONB, '$[0]');
 jsonb 
-------
{"value": 0}
5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?