相关疑难解决方法(0)

LATERAL和PostgreSQL中的子查询有什么区别?

由于Postgres能够进行LATERAL连接,我一直在阅读它,因为我目前为我的团队执行复杂的数据转储,其中包含大量低效的子查询,这使得整个查询需要四分钟或更长时间.

我知道LATERAL联接可能能够帮助我,但即使在阅读了像Heap Analytics 这样的文章之后,我仍然没有完全遵循.

LATERAL加入的用例是什么?LATERAL连接和子查询之间有什么区别?

sql postgresql subquery lateral-join

119
推荐指数
5
解决办法
7万
查看次数

优化GROUP BY查询以检索每个用户的最新记录

我在Postgres 9.2中有下表(简化形式)

CREATE TABLE log (
    log_date DATE,
    user_id  INTEGER,
    payload  INTEGER
);
Run Code Online (Sandbox Code Playgroud)

它每个用户和每天最多包含一条记录.每天将有大约500,000条记录,为期300天.每个用户的running_total总是在增加.

我想在特定日期之前有效地检索每个用户的最新记录.我的查询是:

SELECT user_id, max(log_date), max(payload) 
FROM log 
WHERE log_date <= :mydate 
GROUP BY user_id
Run Code Online (Sandbox Code Playgroud)

这非常慢.我也尝试过:

SELECT DISTINCT ON(user_id), log_date, payload
FROM log
WHERE log_date <= :mydate
ORDER BY user_id, log_date DESC;
Run Code Online (Sandbox Code Playgroud)

具有相同的计划,同样缓慢.

到目前为止,我在user_msg_log(aggr_date)上有一个索引,但没有多大帮助.我应该用什么其他索引来加快速度,还是以任何其他方式实现我的目标?

sql postgresql indexing greatest-n-per-group postgresql-performance

45
推荐指数
3
解决办法
3万
查看次数

如何在SQL查询中使用(func()).*语法避免多重函数的演绎?

上下文

当函数返回a TABLE或a时SETOF composite-type,如此示例函数:

CREATE FUNCTION func(n int) returns table(i int, j bigint) as $$
BEGIN
  RETURN QUERY select 1,n::bigint 
      union all select 2,n*n::bigint
      union all select 3,n*n*n::bigint;
END
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)

结果可以通过各种方法访问:

1)select * from func(3)将产生这些输出列:

 i | j 
---+---
 1 |  3
 2 |  9
 3 | 27

2)select func(3)将只生成一个ROW类型的输出列.

 func  
-------
 (1,3)
 (2,9)
 (3,27)

3)select (func(3)).*会产生#1:

 i | j 
---+---
 1 |  3
 2 |  9
 3 | …

postgresql user-defined-functions

14
推荐指数
1
解决办法
1461
查看次数

如何在 PostgreSQL 9.4+ 中将简单的 json(b) int 数组转换为整数[]

我有一个来自 json 对象的数组:[1, 9, 12]

由于它使用方括号表示法,因为它是直接从 json 对象获取的,所以我无法将其转换为,::integer[]当我尝试使用时,array_agg(jsonb_array_elements(simpleintarray))我收到一条错误消息,说我需要按 id 进行分组,但由于数组不是对象(键/值) )对,但只是简单的整数,我不知道如何以相当有效的方式实现这一点。

从 json 返回上述简单 int 数组的查询是:

SELECT node.*, elem->'permissions' AS group_node_permissions
    FROM node
    LEFT OUTER JOIN
    jsonb_array_elements(my_user_group.node_permissions) elem
    ON elem->>'id' = node.id::text
    ORDER BY node.id
Run Code Online (Sandbox Code Playgroud)

elem->'permissions'理想情况下应该以 Postgres 数组的形式返回{},以便我稍后可以在其上使用该ANY(intarray)函数。

我想避免做多余的低效解决方法,例如用大括号替换方括号,然后转换elem->'permissions'->>整数数组,将其转换为字符串,尽管这可能会起作用。

在伪代码中,我真正需要的是能够得到相同的结果:

SELECT node.*, elem->'permissions'**::integer[]** AS group_node_permissions,

...但是当然由于json 数组与 PostgreSQL 数组格式之间的[]差异{},这会导致错误。

这是我当前的(非常丑陋的解决方案,但有效):

SELECT node.*, replace(replace(elem->>'permissions', '[', '{'),']','}')::integer[] AS group_node_permissions
Run Code Online (Sandbox Code Playgroud)

它将原始的 (jsonb) 转换为(integer[])[1, 9, …

sql arrays postgresql json types

5
推荐指数
1
解决办法
9002
查看次数

如何过滤json列中嵌套值的行?

这是我的表格(简化的,只有重要的列):

CREATE TABLE things (
  id serial primary key
, name varchar
, blueprint json default '{}'
);
Run Code Online (Sandbox Code Playgroud)

以及一些示例数据:

# select * from things;

 id |  name   |                                  blueprint
----+---------+-----------------------------------------------------------------------------
  1 | Thing 1 | {}
  2 | Thing 2 | {"1":{"name":"Iskapola","wight":"2"}}
  3 | Thing 3 | {"1":{"name":"Azamund","weight":"3"}, "2":{"name":"Iskapola","weight":"1"}}
  4 | Thing 4 | {"1":{"name":"Ulamir","weight":"1"}, "2":{"name":"Azamund","weight":"1"}}
Run Code Online (Sandbox Code Playgroud)

我想选择键'Azamund'下任意位置的行name。像这样的东西:

# select * from things where * ->> 'name' = 'Azamund';

 id |      blueprint
----+----------------------------------------------------------------------------
  7 | {"1":{"name":"Azamund","weight":"3"}, "2":{"name":"Iskapola","weight":"1"}} …
Run Code Online (Sandbox Code Playgroud)

sql postgresql json nested

5
推荐指数
1
解决办法
6356
查看次数

PostgreSQL:从返回复合类型的函数中选择

如何在一个函数中包含一个返回复合类型的函数SELECT
我有复合类型:

CREATE TYPE public.dm_nameid AS (
  id   public.dm_int,
  name public.dm_str
);
Run Code Online (Sandbox Code Playgroud)

此外,我有一个函数返回此类型fn_GetLinkedProject(整数).我需要做这样的事情:

SELECT 
    p.id, p.data, p.name, 
    pl.id linked_id, pl.name linked_name
FROM tb_projects p
   left join "fn_GetLinkedProject"(p.id) pl
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

PS我读过这篇文章.

PPS我不想要以下方法:

SELECT
 p.id, p.data, p.name, 
    (select pl1.id from "fn_GetLinkedProject"(p.id) pl1 ) linked_id,
    (select pl2.name from "fn_GetLinkedProject"(p.id) pl2 ) linked_name
FROM tb_projects p
Run Code Online (Sandbox Code Playgroud)

sql postgresql composite left-join lateral-join

3
推荐指数
1
解决办法
3836
查看次数