我有一个data
类型的列,json
其中包含这样的 JSON 文档:
{
"name": "foo",
"tags": ["foo", "bar"]
}
Run Code Online (Sandbox Code Playgroud)
我想将嵌套tags
数组转换为连接字符串 ( 'foo, bar'
)。array_to_string()
从理论上讲,使用该函数很容易做到这一点。但是,此功能不接受json
输入。所以我想知道如何将这个 JSON 数组变成 Postgres 数组(类型text[]
)?
在多对多关系上使用 join 时,结果会拆分为多行。我想做的是将连接的右侧转换为数组,因此结果是一行。
包含 3 个表的示例:
CREATE TABLE items (
id serial primary key,
title text
);
CREATE TABLE tags (
id serial primary key,
title text
);
CREATE TABLE items_tags (
item_id int references items(id),
tag_id int references tags(id),
primary key (item_id, tag_id)
);
Run Code Online (Sandbox Code Playgroud)
选择带有标签的项目时,我可以这样做:
SELECT i.id, i.title, i.title
FROM items i
INNER JOIN items_tags it
ON it.item_id = i.id
INNER JOIN tags t
ON t.id = it.tag_id;
Run Code Online (Sandbox Code Playgroud)
结果将显示为:
(1, "item n1", "sport")
(1, "item n1", "soccer")
(2, "item …
Run Code Online (Sandbox Code Playgroud) 我刚刚查看了一些为8.4 之前的 PostgreSQL编写的旧代码,我看到了一些非常棒的东西。我记得以前有一个自定义函数可以做一些这样的事情,但我忘记了预先的array_agg()
样子。回顾一下,现代聚合是这样写的。
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
Run Code Online (Sandbox Code Playgroud)
然而,曾几何时,它是这样写的,
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
Run Code Online (Sandbox Code Playgroud)
所以,我用一些测试数据试了一下..
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
Run Code Online (Sandbox Code Playgroud)
结果令人惊讶..#OldSchoolCool 方式要快得多:加速了 25%。此外,在没有ORDER 的情况下简化它,表现出同样的缓慢。
# EXPLAIN ANALYZE SELECT ARRAY(SELECT x FROM foobar);
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Result (cost=104425.28..104425.29 rows=1 width=0) (actual time=1665.948..1665.949 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Seq Scan on foobar (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.032..716.793 rows=10000000 loops=1) …
Run Code Online (Sandbox Code Playgroud) 我有一个看起来像这样的表(在 PostgreSQL 9.4 中):
CREATE TABLE dates_ranges (kind int, start_date date, end_date date);
INSERT INTO dates_ranges VALUES
(1, '2018-01-01', '2018-01-31'),
(1, '2018-01-01', '2018-01-05'),
(1, '2018-01-03', '2018-01-06'),
(2, '2018-01-01', '2018-01-01'),
(2, '2018-01-01', '2018-01-02'),
(3, '2018-01-02', '2018-01-08'),
(3, '2018-01-05', '2018-01-10');
Run Code Online (Sandbox Code Playgroud)
现在我想计算给定日期和每种类型,计算dates_ranges
每个日期有多少行。零可以省略。
想要的结果:
+-------+------------+----+
| kind | as_of_date | n |
+-------+------------+----+
| 1 | 2018-01-01 | 2 |
| 1 | 2018-01-02 | 2 |
| 1 | 2018-01-03 | 3 |
| 2 | 2018-01-01 | 2 |
| …
Run Code Online (Sandbox Code Playgroud) 我正在使用 Postgres 9.3,我需要根据表中已有的特定行数来防止插入到表中。这是表:
Table "public.team_joins"
Column | Type | Modifiers
-----------------+--------------------------+---------------------------------------------------------
id | integer | not null default nextval('team_joins_id_seq'::regclass)
team_id | integer | not null
Indexes:
"team_joins_pkey" PRIMARY KEY, btree (id)
"team_joins_team_id" btree (team_id)
Foreign-key constraints:
"team_id_refs_teams_id" FOREIGN KEY (team_id) REFERENCES teams(id) DEFERRABLE INITIALLY DEFERRED
Run Code Online (Sandbox Code Playgroud)
因此,例如,如果一个 id 为 3 的团队只允许 20 名玩家,并且SELECT COUNT(*) FROM team_joins WHERE team_id = 3
等于 20,那么没有玩家应该能够加入团队 3。处理这种情况并避免并发问题的最佳方法是什么?我应该使用SERIALIZABLE
事务来插入,还是可以WHERE
在插入语句中使用这样的子句?
INSERT INTO team_joins (team_id)
VALUES (3)
WHERE (
SELECT COUNT(*) FROM team_joins WHERE …
Run Code Online (Sandbox Code Playgroud) 我有一个返回 CTE 的查询,如下所示
+-----------+-------------+
| node_id | ancestors |
|-----------+-------------|
| 1 | [] |
| 2 | [] |
| 3 | [1] |
| 4 | [2] |
| 5 | [4, 2] |
+-----------+-------------+
Run Code Online (Sandbox Code Playgroud)
我想要做的是加入表nodes
并将该列中的 id 替换ancestors
为表中的另一列nodes
。这是我到目前为止的查询:
WITH RECURSIVE tree AS (
-- snip --
)
SELECT node.entity_id AS id,
array_remove(array_agg(parent_nodes.entity_id), NULL) AS ancestors
FROM tree
JOIN entity.nodes AS node ON node.id = tree.node_id
LEFT OUTER JOIN entity.nodes AS parent_nodes ON …
Run Code Online (Sandbox Code Playgroud)