在 Postgres 的 json 列中将 LocalDate 转换为时间戳
Convert LocalDate into Timestamp in Postgres' json column
我必须迁移 PostgresDB 9.5 中的列。
table 名称是 testtable,相关列是 examplecolumn。
在示例列中,我有这个 JSON 数组,例如:
[{"key":"id","before":null,"after":4371},
{"key":"status","before":null,"after":1},
{"key":"startDate","before":null,"after":1514761200000},
{"key":"endDate","before":null,"after":1546297199000},
{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}]
我想将带有 "billingDate" 的 child 转换为以下格式的时间戳:
[{"key":"id","before":null,"after":4371},
{"key":"status","before":null,"after":1},
{"key":"startDate","before":null,"after":1514761200000},
{"key":"endDate","before":null,"after":1546297199000},
{"billingDate":1515974400}]
我想保留其他所有东西。首先我试着像这样获取这些行。
SELECT *, examplecolumn::json->4->'after' as export
FROM testtable
WHERE examplecolumn like '%after":{%';
但是我不能用固定索引(例如 4)来做到这一点,而且我不知道哪一行有 child objects 和这个 LocalDate,这就是为什么我写这个 where-clause.
我该怎么做?我用几个 Postgres JSON 函数尝试了很多次,但我受够了。
谢谢。
我不清楚问题是根据问题的标题将数据转换为时间戳,还是根据问题提取数据。所以这个答案是关于提取数据的。
首先,CTE 只是随机化 JSON 数组中项目的顺序,以表明它绕过了索引问题。显然,您将改为在 table 上执行查询。那么带"billingDate"的项只包含在偶数结果中;奇数包含 JSON 项的其余部分并排除该项。
WITH cte AS (
SELECT ('[' || STRING_AGG(CASE WHEN id = 2 THEN CASE WHEN g % 2 = 0 THEN j::TEXT END ELSE j::TEXT END, ',' ORDER BY RANDOM()) || ']')::JSON AS j
FROM (
VALUES
(1, '{"key":"id","before":null,"after":4371}'),
(1, '{"key":"status","before":null,"after":1}'),
(1, '{"key":"startDate","before":null,"after":1514761200000}'),
(1, '{"key":"endDate","before":null,"after":1546297199000}'),
(2, '{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}')
) AS v(id, j), generate_series(1, 10) AS g
GROUP BY g
)
SELECT j, (SELECT je->'after' FROM JSON_ARRAY_ELEMENTS(j) AS je WHERE je->>'key' = 'billingDate' AND (je->>'after') IS NOT NULL) AS export
FROM cte
结果:
如果您只想获取具有 "billingDate" 的项目,那么您可以从您的问题中添加 WHERE 子句:
WITH cte AS (
SELECT ('[' || STRING_AGG(CASE WHEN id = 2 THEN CASE WHEN g % 2 = 0 THEN j::TEXT END ELSE j::TEXT END, ',' ORDER BY RANDOM()) || ']')::JSON AS j
FROM (
VALUES
(1, '{"key":"id","before":null,"after":4371}'),
(1, '{"key":"status","before":null,"after":1}'),
(1, '{"key":"startDate","before":null,"after":1514761200000}'),
(1, '{"key":"endDate","before":null,"after":1546297199000}'),
(2, '{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}')
) AS v(id, j), generate_series(1, 10) AS g
GROUP BY g
)
SELECT j, (SELECT je->'after' FROM JSON_ARRAY_ELEMENTS(j) AS je WHERE je->>'key' = 'billingDate' AND (je->>'after') IS NOT NULL) AS export
FROM cte
WHERE j::TEXT LIKE '%after":{%'
结果:
我必须迁移 PostgresDB 9.5 中的列。
table 名称是 testtable,相关列是 examplecolumn。
在示例列中,我有这个 JSON 数组,例如:
[{"key":"id","before":null,"after":4371},
{"key":"status","before":null,"after":1},
{"key":"startDate","before":null,"after":1514761200000},
{"key":"endDate","before":null,"after":1546297199000},
{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}]
我想将带有 "billingDate" 的 child 转换为以下格式的时间戳:
[{"key":"id","before":null,"after":4371},
{"key":"status","before":null,"after":1},
{"key":"startDate","before":null,"after":1514761200000},
{"key":"endDate","before":null,"after":1546297199000},
{"billingDate":1515974400}]
我想保留其他所有东西。首先我试着像这样获取这些行。
SELECT *, examplecolumn::json->4->'after' as export
FROM testtable
WHERE examplecolumn like '%after":{%';
但是我不能用固定索引(例如 4)来做到这一点,而且我不知道哪一行有 child objects 和这个 LocalDate,这就是为什么我写这个 where-clause.
我该怎么做?我用几个 Postgres JSON 函数尝试了很多次,但我受够了。
谢谢。
我不清楚问题是根据问题的标题将数据转换为时间戳,还是根据问题提取数据。所以这个答案是关于提取数据的。
首先,CTE 只是随机化 JSON 数组中项目的顺序,以表明它绕过了索引问题。显然,您将改为在 table 上执行查询。那么带"billingDate"的项只包含在偶数结果中;奇数包含 JSON 项的其余部分并排除该项。
WITH cte AS (
SELECT ('[' || STRING_AGG(CASE WHEN id = 2 THEN CASE WHEN g % 2 = 0 THEN j::TEXT END ELSE j::TEXT END, ',' ORDER BY RANDOM()) || ']')::JSON AS j
FROM (
VALUES
(1, '{"key":"id","before":null,"after":4371}'),
(1, '{"key":"status","before":null,"after":1}'),
(1, '{"key":"startDate","before":null,"after":1514761200000}'),
(1, '{"key":"endDate","before":null,"after":1546297199000}'),
(2, '{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}')
) AS v(id, j), generate_series(1, 10) AS g
GROUP BY g
)
SELECT j, (SELECT je->'after' FROM JSON_ARRAY_ELEMENTS(j) AS je WHERE je->>'key' = 'billingDate' AND (je->>'after') IS NOT NULL) AS export
FROM cte
结果:
如果您只想获取具有 "billingDate" 的项目,那么您可以从您的问题中添加 WHERE 子句:
WITH cte AS (
SELECT ('[' || STRING_AGG(CASE WHEN id = 2 THEN CASE WHEN g % 2 = 0 THEN j::TEXT END ELSE j::TEXT END, ',' ORDER BY RANDOM()) || ']')::JSON AS j
FROM (
VALUES
(1, '{"key":"id","before":null,"after":4371}'),
(1, '{"key":"status","before":null,"after":1}'),
(1, '{"key":"startDate","before":null,"after":1514761200000}'),
(1, '{"key":"endDate","before":null,"after":1546297199000}'),
(2, '{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}')
) AS v(id, j), generate_series(1, 10) AS g
GROUP BY g
)
SELECT j, (SELECT je->'after' FROM JSON_ARRAY_ELEMENTS(j) AS je WHERE je->>'key' = 'billingDate' AND (je->>'after') IS NOT NULL) AS export
FROM cte
WHERE j::TEXT LIKE '%after":{%'
结果: