【问题标题】:How to count records of an array with condition in PostgreSQL如何在 PostgreSQL 中计算具有条件的数组的记录
【发布时间】:2017-06-10 11:31:27
【问题描述】:

我有例如一个表“员工”与

last_name :: character varying
handed_texts :: text[]

其中 text 是自己的数据类型,带有 "("Date", title/not_exist)"。

x := ({}, 1,2,...) 时可能有 x 个条目

例子:

jones , {"(2017-01-01, stars_in_univ)", "(2017-01-01, not_exist)",   "(2017-01-02, unemployed ants)"}
tomes , {"(2017-01-01, not_exist)", "(2017-01-08, shared_minds)"}

我现在的问题:我想计算每个名字的现有文本。 我试过了,例如类似的东西:

SELECT last_name, handed_texts,
       CASE
           WHEN handed_texts IS NULL THEN 0
           ELSE
               FOREACH i IN ARRAY handed_texts
               DECLARE c integer;
               SET c = 0;
               LOOP
                   IF i NOT LIKE '%not_exist%' THEN c+1 ELSE c END IF
                 return c
              END LOOP
      END AS counted_texts
FROM employee

我知道声明是完全错误的,但我找不到任何方法以我的系统接受的方式声明变量,所以我只是在我认为应该声明的地方写了它。 我试图计算的另一种方法是创建一个新数组,我只需将正确/想要的记录放入并使用 array_length,但这似乎比上面的例子更具灾难性。

【问题讨论】:

  • 定义自己的数据类型与现有的内置数据类型同名不是一个好主意
  • 谢谢,没错。但是我发现一个简短的例子没有这么快。也许只是将其称为具有相同定义的协议...。

标签: sql arrays postgresql loops conditional-statements


【解决方案1】:

您可以将其转换为字符串,并使用标准的 LIKE 构造:

select last_name, count(*) 
from (select last_name, array_to_string(handed_texts,',','') t
      from employee e2) a
where a.t like '%not_exist%
group by last_name;

抱歉,我的rextester 的翻译漏掉了

【讨论】:

  • SELECT last_name, handed_texts, count() as num FROM (SELECT last_name, handed_texts, array_to_string(handed_texts,',','') t FROM employee) a WHERE at NOT LIKE '% not_exist%' GROUP BY last_name, handed_texts, count() as num 我的计数始终为 1。但我在上面的示例和问题中发现了我的错误,并使用 handed_texts - 数组制作了一个更好的示例并使问题更多精确的。首先:在数组中可以有 x 个条目 x := ({}, 1,2,....) 我需要每个名称本身的 handed_texts 计数。
【解决方案2】:

我不能保证它是有效的,但如果你取消嵌套并重新聚合,这似乎是可能的:

with exploded as (
  select last_name, unnest (handed_texts) as handed
  from employee
)
select
  last_name, array_agg (handed) as handed_texts
from exploded
where
  handed not like '%not_exist%'
group by last_name

也就是说,如果您像这样将 handed_texts 更改为自己的表格:

create table handed_texts (
   last_name varchar,
   title_date date,
   title_name text
)

并且加入了姓氏,我认为它可能会提供一个更清洁的解决方案。

【讨论】:

  • 这似乎是个好主意,但/我的问题是,未知的可能性。所以我应该做一个案例,在其中为 {} 填写 0。这将是可行的。谢谢。是的,像你写的那样改变它是个好主意,但它是给定的,我必须工作/处理它...... .
  • 尝试对您的数据提出建议并告诉我。同样,我不保证它很快,但我确实认为它是可扩展的。
  • 我现在发现了问题:UNNEST 确实有效,没问题。然后:姓氏递给 jones (2017-01-01,stars_in_univ) jones (2017-01-01,not_exist) jones (2017-01-02,unused ants) tomes (2017-01-01,not_exist) tomes (2017-01 -08, shared_minds) 当我现在使用 WHERE handed NOT LIKE '%not_exist%' 时,错误运算符不存在:布尔值!~~未知字符 XXX 提示:没有运算符与给定名称和参数类型匹配。您可能需要添加显式类型转换它目前并没有真正帮助我。但是到目前为止
  • 这很好奇...您可以为您的表发布 DDL 吗?您说handed_texts 列是text[]——text 的数组,对吗?当您在 PgAdmin 中运行子查询(带有 unnest)时,它列出了名为 handed 的列的数据类型是什么?我看不出我的任何代码如何产生布尔值!
【解决方案3】:

unnest 函数在这里可能很有用。你可以这样使用它:

SELECT e.id, COUNT(texts.id)
FROM employee AS e
LEFT JOIN (
    -- this "unfolds" all arrays as if they were a single table of all texts of all employees
    SELECT id, UNNEST(handed_texts) AS handed_texts
    FROM employee
) AS texts ON texts.id = e.id
WHERE ... -- any condition on single array element being now in texts "table"
GROUP BY e.id

【讨论】:

  • 谢谢到目前为止。我得到错误:运算符不存在:文本!~~未知。这似乎与我在 Hambones 的回答中得到的错误相同。
猜你喜欢
  • 2013-04-21
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 2021-08-23
  • 2023-01-17
  • 2021-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多