9. WITH RECURSIVE t(id, value) AS (
SELECT * FROM js_test
UNION ALL (
SELECT
t.id,
COALESCE(kv.value, e.value) AS value
FROM t
LEFT JOIN LATERAL jsonb_each(
CASE WHEN jsonb_typeof(t.value) ='object'
THEN t.value ELSE NULL END
) kv ON true
LEFT JOIN LATERAL jsonb_array_elements(
CASE WHEN jsonb_typeof(t.value) = 'array'
THEN t.value ELSE NULL END
) e ON true
WHERE
kv.value IS NOT NULL
OR e.value IS NOT NULL
)
)
SELECT js_test.* FROM (
SELECT id FROM t
WHERE
value @> '{"color":"red"}'
GROUP BY id
) x
JOIN js_test ON js_test.id = x.id;
Найти "что-нибудь" красное
11. SELECT * FROM js_test
WHERE
value @@ '*.color = "red"';
JSQuery
https://github.com/postgrespro/jsquery
12. • Новый тип данных jsonpath
• Функции для конструирования JSON
• Функции для выполнения запросов к JSON-полям
SQL / JSON (SQL-2016)
SELECT * FROM js_test
WHERE
JSON_EXISTS(value, '$.**.color ? (@ == "red")');
15. JSON-агрегация
SELECT * FROM users
LEFT JOIN comments ON comments.user_id = users.id
users.id users.name comments.id comments.text comments.user_id comments.created_at
1 alice 1 hello 1 31.12.2017 23:59:50
1 alice 2 Happy NY! 1 01.01.2018 00:00:10
2 bob 3 You too! 2 01.01.2018 00:00:50
16. JSON-агрегация
select
users.*, json_agg(comments.*) as comments
from users
left join comments on comments.user_id = users.id
group by users.id
users.id users.name comments
1 alice [
{ id: 1, text: "hello", created_at: "31.12.2017 23:59:50" },
{ id: 2, text: "Happy NY!", created_at: "01.01.2018 00:00:10"}
]
2 bob [{ id: 3, text: "You too!", created_at: "01.01.2018 00:00:50"}]
17. JSON-агрегация
select
users.*, json_agg(comments.* ORDER BY created_at DESC) as comments
from users
left join comments on comments.user_id = users.id
group by users.id
users.id users.name comments
1 alice [
{ id: 1, text: "hello", created_at: "31.12.2017 23:59:50" },
{ id: 2, text: "Happy NY!", created_at: "01.01.2018 00:00:10"}
]
2 bob [{ id: 3, text: "You too!", created_at: "01.01.2018 00:00:50"}]
18. Оконные функции
select * from events
id type source_id created_at
1 foo 1
2 bar 2
3 a 1
4 b 2
5 c 3
6 d 1
7 e 1
Последние два события по каждому source_id?
19. Оконные функции
SELECT ROW_NUMBER() OVER (PARTITION by source_id) as row_number, * from events
row_number id type source_id created_at
1 7 e 1
2 6 d 1
3 3 a 1
4 1 foo 1
1 4 b 2
2 2 bar 2
1 5 c 3
Последние два события по каждому source_id?
20. Оконные функции
WITH events_cte AS (
SELECT
row_number() OVER (PARTITION by source_id) AS row_number, *
FROM events
) SELECT * FROM events_cte WHERE row_number <= 2
row_nunmber id type source_id created_at
1 7 e 1
2 6 d 1
1 4 b 2
2 2 bar 2
1 5 c 3
21. Оконные функции
• Все агрегирующие функции
• row_number, rank, dense_rank, percent_rank, cum_dist
• ntile(n)
• lag(value), lead(value)
• first_value, last_value, nth_value