PostgreSQL JSONB 查询每个键的类型
PostgreSQL JSONB query types of each keys
我有一定的table:
CREATE TABLE x(
id BIGSERIAL PRIMARY KEY,
data JSONB
);
INSERT INTO x(data)
VALUES( '{"a":"test", "b":123, "c":null, "d":true}' ),
( '{"a":"test", "b":123, "c":null, "d":"yay", "e":"foo", "f":[1,2,3]}' );
如何查询 table 中每个键的类型,因此它会给出如下输出:
a | string:2
b | number:2
c | null:2
d | boolean:1 string:1
e | string:1
f | jsonb:1 -- or anything
我只知道获取key的方法和计数,不知道怎么获取每个key的类型:
SELECT jsonb_object_keys(data), COUNT(id) FROM x GROUP BY 1 ORDER BY 1
这会给出类似的东西:
a | 2
b | 2
c | 2
d | 2
e | 1
f | 1
编辑:
正如 pozs 指出的那样,有两个 typeof
函数:一个用于 JSON,一个用于 SQL。此查询是您要查找的查询:
SELECT
json_data.key,
jsonb_typeof(json_data.value),
count(*)
FROM x, jsonb_each(x.data) AS json_data
group by key, jsonb_typeof
order by key, jsonb_typeof;
旧答案:(嘿,它有效...)
此查询将 return 键的类型:
SELECT
json_data.key,
pg_typeof(json_data.value),
json_data.value
FROM x, jsonb_each(x.data) AS json_data;
...不幸的是,您会注意到 Postgres 不区分不同的 JSON 类型。它认为这一切都是jsonb
,所以结果是:
key1 | value1 | value
------+--------+-----------
a | jsonb | "test"
b | jsonb | 123
c | jsonb | null
d | jsonb | true
a | jsonb | "test"
b | jsonb | 123
c | jsonb | null
d | jsonb | "yay"
e | jsonb | "foo"
f | jsonb | [1, 2, 3]
(10 rows)
然而,并没有那么多JSON primitive types,并且输出似乎没有歧义。所以此查询将执行您想要的操作:
with jsontypes as (
SELECT
json_data.key AS key1,
CASE WHEN left(json_data.value::text,1) = '"' THEN 'String'
WHEN json_data.value::text ~ '^-?\d' THEN
CASE WHEN json_data.value::text ~ '\.' THEN 'Number'
ELSE 'Integer'
END
WHEN left(json_data.value::text,1) = '[' THEN 'Array'
WHEN left(json_data.value::text,1) = '{' THEN 'Object'
WHEN json_data.value::text in ('true', 'false') THEN 'Boolean'
WHEN json_data.value::text = 'null' THEN 'Null'
ELSE 'Beats Me'
END as jsontype
FROM x, jsonb_each(x.data) AS json_data -- Note that it won't work if we use jsonb_each_text here because the strings won't have quotes around them, etc.
)
select *, count(*) from jsontypes
group by key1, jsontype
order by key1, jsontype;
输出:
key1 | jsontype | count
------+----------+-------
a | String | 2
b | Integer | 2
c | Null | 2
d | Boolean | 1
d | String | 1
e | String | 1
f | Array | 1
(7 rows)
您可以使用 jsonb_typeof
改进上次查询
with jsontypes as (
SELECT
json_data.key AS key1,
jsonb_typeof(json_data.value) as jsontype
FROM x, jsonb_each(x.data) AS json_data
)
select *, count(*)
from jsontypes
group by 1, 2
order by 1, 2;
我有一定的table:
CREATE TABLE x(
id BIGSERIAL PRIMARY KEY,
data JSONB
);
INSERT INTO x(data)
VALUES( '{"a":"test", "b":123, "c":null, "d":true}' ),
( '{"a":"test", "b":123, "c":null, "d":"yay", "e":"foo", "f":[1,2,3]}' );
如何查询 table 中每个键的类型,因此它会给出如下输出:
a | string:2
b | number:2
c | null:2
d | boolean:1 string:1
e | string:1
f | jsonb:1 -- or anything
我只知道获取key的方法和计数,不知道怎么获取每个key的类型:
SELECT jsonb_object_keys(data), COUNT(id) FROM x GROUP BY 1 ORDER BY 1
这会给出类似的东西:
a | 2
b | 2
c | 2
d | 2
e | 1
f | 1
编辑:
正如 pozs 指出的那样,有两个 typeof
函数:一个用于 JSON,一个用于 SQL。此查询是您要查找的查询:
SELECT
json_data.key,
jsonb_typeof(json_data.value),
count(*)
FROM x, jsonb_each(x.data) AS json_data
group by key, jsonb_typeof
order by key, jsonb_typeof;
旧答案:(嘿,它有效...)
此查询将 return 键的类型:
SELECT
json_data.key,
pg_typeof(json_data.value),
json_data.value
FROM x, jsonb_each(x.data) AS json_data;
...不幸的是,您会注意到 Postgres 不区分不同的 JSON 类型。它认为这一切都是jsonb
,所以结果是:
key1 | value1 | value
------+--------+-----------
a | jsonb | "test"
b | jsonb | 123
c | jsonb | null
d | jsonb | true
a | jsonb | "test"
b | jsonb | 123
c | jsonb | null
d | jsonb | "yay"
e | jsonb | "foo"
f | jsonb | [1, 2, 3]
(10 rows)
然而,并没有那么多JSON primitive types,并且输出似乎没有歧义。所以此查询将执行您想要的操作:
with jsontypes as (
SELECT
json_data.key AS key1,
CASE WHEN left(json_data.value::text,1) = '"' THEN 'String'
WHEN json_data.value::text ~ '^-?\d' THEN
CASE WHEN json_data.value::text ~ '\.' THEN 'Number'
ELSE 'Integer'
END
WHEN left(json_data.value::text,1) = '[' THEN 'Array'
WHEN left(json_data.value::text,1) = '{' THEN 'Object'
WHEN json_data.value::text in ('true', 'false') THEN 'Boolean'
WHEN json_data.value::text = 'null' THEN 'Null'
ELSE 'Beats Me'
END as jsontype
FROM x, jsonb_each(x.data) AS json_data -- Note that it won't work if we use jsonb_each_text here because the strings won't have quotes around them, etc.
)
select *, count(*) from jsontypes
group by key1, jsontype
order by key1, jsontype;
输出:
key1 | jsontype | count
------+----------+-------
a | String | 2
b | Integer | 2
c | Null | 2
d | Boolean | 1
d | String | 1
e | String | 1
f | Array | 1
(7 rows)
您可以使用 jsonb_typeof
改进上次查询with jsontypes as (
SELECT
json_data.key AS key1,
jsonb_typeof(json_data.value) as jsontype
FROM x, jsonb_each(x.data) AS json_data
)
select *, count(*)
from jsontypes
group by 1, 2
order by 1, 2;