小编Roc*_*nja的帖子

避免 PG::TRDeadlockDetected

我在批量插入中使用下面的函数,通常批量插入有大约 60 行,每行都有下面的函数。但有时我会收到 PG::TRDeadlockDetected: ERROR: deadlock detected(请参阅下面的完整错误)。

我怎样才能避免这种情况?如果发生这种情况,我可以添加一个将返回 0 的 EXCEPTION,我宁愿不这样做,但批量插入对我来说非常方便。

CREATE OR REPLACE FUNCTION "univ"."gc_title_desc"(IN _title text, IN _desc text, OUT result_id int4) RETURNS "int4" 
AS $BODY$BEGIN
LOOP
BEGIN
WITH sel AS (
  SELECT id
  FROM   univ.results
  WHERE  title = _title AND description = _desc
  )
, ins AS (
  INSERT INTO univ.results (title, description)
  SELECT _title, _desc
  WHERE  NOT EXISTS (SELECT 1 FROM sel)
  RETURNING id
  )
SELECT id
FROM   sel NATURAL FULL OUTER JOIN ins 
INTO   result_id; …
Run Code Online (Sandbox Code Playgroud)

postgresql postgresql-9.3

7
推荐指数
1
解决办法
5605
查看次数

返回总行数和选定(聚合)数据

我有一个从表格中选择一些数据的功能。我想返回所选数据和该表中的总行数。

我怎样才能做到这一点,或者我怎样才能以最有效的方式获得相同的结果?

我尝试了几件事,最后得到了下面的代码,现在这是我想要的格式,但count(*) over () as total_count会一直返回 1,我需要它返回的是该records选择的总行数。

SELECT 
row_to_json(selected_records) as data
FROM
(   
    SELECT
    count(*) over () as total_count,
    array_to_json(array_agg(row_to_json(records))) as data
    FROM (
        SELECT
            sum(entrances) as entrances
        FROM report_la
        WHERE profile_id = 3777614
        GROUP BY landing_path_id
        limit 10 offset 0
    ) records
) as selected_records
Run Code Online (Sandbox Code Playgroud)

更新,下面的代码产生了我想要的结果,如果我可以total_countrecords选择中隐藏该列就好了

SELECT 
row_to_json(selected_records) as data
FROM
(   
    SELECT
    min(total_count) as total_count
    ,array_to_json(array_agg(row_to_json(records))) as data
    FROM (
        SELECT
            sum(entrances) as entrances
            ,count(*) over () as total_count …
Run Code Online (Sandbox Code Playgroud)

postgresql aggregate window-functions postgresql-9.3

6
推荐指数
1
解决办法
2万
查看次数

仅当元素不存在时才将元素追加到数组

WITH upd AS (
  UPDATE univ.products
  SET source = source::int[] || _source
  WHERE project_id = _project_id AND product_id = _products AND NOT(_source = ANY(source))
  RETURNING id
)

, ins AS (
  INSERT INTO univ.products(project_id, product_id, source, tracked)
  SELECT _project_id, _product_id, ARRAY[_source], _tracked
  WHERE NOT EXISTS (SELECT 1 FROM upd) 
  RETURNING id
 )

SELECT id
FROM   upd NATURAL FULL OUTER JOIN ins 
INTO   _project_product_id;
Run Code Online (Sandbox Code Playgroud)

我的情况,我有这个函数,其中包含上述所有内容以及更多内容,我试图避免重复项目/产品对,但同时通过附加新源来更新源。现在每个产品/项目对的源必须是唯一的,这就是我添加的原因NOT(_source = ANY(source)),但如果这是真的,select 1 from up将不会返回任何内容,因此将尝试将记录插入数据库以避免这种情况,我添加了以下内容例外。

EXCEPTION WHEN UNIQUE_VIOLATION THEN
    EXIT;
END;
Run Code Online (Sandbox Code Playgroud)

这几乎是我想要的,但没有返回任何 …

postgresql postgresql-9.3

6
推荐指数
1
解决办法
5590
查看次数

将生成的系列与选择中的每一行结合起来

下面的选择返回我所有用户拥有的所有项目的数组。

WITH user_projects AS
(SELECT
  u.id as user_id
  ,COALESCE(array_agg(DISTINCT pa.project_id), '{0}'::integer[]) as project_ids
FROM users u
LEFT JOIN project_assignments pa on pa.user_creator_id = u.id
GROUP BY u.id
)

user: 1, project_ids: {1, 2}
user: 2, project_ids: {3, 4}
Run Code Online (Sandbox Code Playgroud)

使用该选择,我想进行报告,该报告将为每个用户显示 12 个月的摘要。

SELECT
  to_char(pk.created_at,'Mon') as mon
 ,extract(year from pk.created_at) as yyyy
 ,up.user_id
 ,COALESCE(count(distinct pk.keyword_id), 0) as total_keywords
FROM user_projects up
LEFT JOIN project_keywords pk on pk.project_id = ANY(up.project_ids::int[])
GROUP BY up.user_id, up.project_ids, 1, 2
Run Code Online (Sandbox Code Playgroud)

输出:

 mon: sept, yyyy: 2014, user_id: 1, …
Run Code Online (Sandbox Code Playgroud)

postgresql join

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

插入或选择后返回id

我想构建一个函数,如果表中不存在电子邮件值并返回email_id行的值,则该函数将插入电子邮件。我怎样才能做到这一点?
另外,如果电子邮件没有插入并且它已经存在于数据库中,我该如何返回 ID?我需要执行另一个SELECT吗?

BEGIN;
  LOCK TABLE mailing_list IN SHARE ROW EXCLUSIVE MODE;
  INSERT INTO mailing_list (email)
  SELECT 'email'
   WHERE NOT EXISTS (
     SELECT * FROM mailing_list WHERE email='email'
   );
COMMIT;
Run Code Online (Sandbox Code Playgroud)

我试过添加,returning id但它不起作用。我有:

查询没有结果数据的目的地

Sqlfiddle

postgresql insert concurrency plpgsql postgresql-9.3

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

批量插入多个表

我有两个表可以执行一些批量插入:

  1. 密钥:key_id (pk), key_name
  2. related_key: related_key_id (pk), key_id (fk)

第一INSERT

values_data = "($$key_1$$), ($$key_2$$)"

INSERT INTO key (key_name) VALUES values_data
Run Code Online (Sandbox Code Playgroud)

INSERT

values_data = "(1, `the id of the first value inserted in key`)
             , (1, `the id of the sec value inserted in key`)"

INSERT INTO related_key (related_key_id, key_id) VALUES values_data
Run Code Online (Sandbox Code Playgroud)

我不知道如何做第二个,INSERT因为我不知道如何为插入到key表中的行获取这些 id 。

或者有没有更好的方法来做到这一点?

postgresql cte postgresql-9.3 bulk-insert

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

根据条件选择和计数

我有两个表,proj: id nameproj_reports: id, position, created_at, key_id, proj_id我想从选择key_reports每个proj_id

- total number of `key_id` which can be done with `count(.key_id)`
- total number of DISTINCT `key_id` `count(DISTINCT .key_id)`
- total number of `key_id` where `position` > 1
- total number of `key_id` where `position` > 2 AND < 5
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我不知道如何添加这些条件来检查位置是 > 或 < 一个数字还是在一个范围内。

postgresql

2
推荐指数
1
解决办法
5307
查看次数

根据列获得不同的结果并满足条件

我有以下选择,它是从带有列的表中选择的:

id、project_id、keyword_id、位置、数据示例:

i, p_id, k_id, p 
1,  1,    1,   4
2,  1,    1,   5
3,  1,    1,   6
5,  1,    2,   7
6,  1,    2,   8
7,  1,    3,   5
8,  1,    3,   7
Run Code Online (Sandbox Code Playgroud)

询问

SELECT
  pr.project_id,
  COUNT(DISTINCT pr.keyword_id) as total_keywords,
  COUNT(CASE WHEN position BETWEEN 4 AND 10 THEN position ELSE NULL END ) AS pos4,
  date(pr.created_at) AS created_at
FROM
  project_reports pr
GROUP BY pr.project_id, date(created_at)
Run Code Online (Sandbox Code Playgroud)

我只想在 pos 4-10 中获取不同的 keyword_id 的数量。但是使用我的SELECT我得到了所有这些。

预期数据示例:

p_id, total_keywords, pos4
1,      3, …
Run Code Online (Sandbox Code Playgroud)

postgresql postgresql-9.2 postgresql-9.3

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

使用实体化视图

我有一个物化视图,创建大约需要 57 秒,并且我使用的是 PostgreSQL 9.4。

当我插入表时,触发器将调用触发器函数,该函数将REFRESH MATERIALIZED VIEW CONCURRENTLY view触发触发器after each statement(插入、更新、删除)

发生的情况是,执行插入操作大约需要 57 秒。

如何解决此问题并仍然使用物化视图?

我已经实现了很长时间,从来没有出现过这个问题,最近我添加了pgbouncer,会不会是这个原因?

postgresql materialized-view pgbouncer postgresql-9.4

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

减少对同一张表的查询次数

我需要使用两个表构建一些报告:

AuthorTitles: id(pk), author_id, title_id
AuthorReports: id(pk), author_id, title_id, items_sold, date
Run Code Online (Sandbox Code Playgroud)

我的报告需要输出以下内容: author_id, max_items_sold_wavg, items_sold_wavg, date

下面的代码可能有一些错误,请检查小提琴。

max_items_sold_wavg 是空闲查询的加权平均值:

WITH maxitems AS ( 
 SELECT
   at.author_id,
   at.title_id,
   max(ar.items_sold) as sold,
   ar.date::date as date
 FROM author_titles at
 LEFT JOIN author_reports ar ON ar.author_id = at.author_id AND at.title_id = ar.title_id
 GROUP BY 1, 2, 4
), totitems AS (
    SELECT
      mi.author_id
      count(ti.title_id) as total,
      count(CASE WHEN (mi.sold = 1) THEN mi.title_id END) AS sold1,
      count(CASE WHEN (mi.sold = 2) THEN mi.title_id END) AS …
Run Code Online (Sandbox Code Playgroud)

postgresql postgresql-9.3

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

从表中获取最小和最大行

从带有列的表中: id(pk), type_id, book_id, title_id, page_id, lines(int4), created_at(date)

如何选择带有min(lines)max(lines)for (type_id, book_id, title_id, page_id) 的行以及created_atwhen min(lines) 的值和最大值的值。

虚拟数据:

type_id, book_id, title_id, page_id, lines, created_at
1, 1, 1, 1, 12, 2015-04-01
1, 1, 1, 1, 10, 2015-03-01
1, 1, 1, 1, 11, 2015-03-02
1, 1, 1, 2, 3, 2015-04-01
1, 1, 1, 2, 5, 2015-03-01
1, 1, 1, 2, 6, 2015-03-04
Run Code Online (Sandbox Code Playgroud)

预期输出:

type_id, book_id, title_id, page_id, min, min_created_at, max, max_created_at
1, 1, 1, 1, 10, 2015-03-01, …
Run Code Online (Sandbox Code Playgroud)

postgresql postgresql-9.4

0
推荐指数
1
解决办法
3624
查看次数