开发者

How to combine particular rows in a pl/pgsql function that returns set of a view row type?

I have a view, and I have a function that returns records from this view. Here is the view definition:

CREATE VIEW ctags(id, name, descr, freq) AS                               
SELECT tags.conc_id, expressions.name, concepts.descr, tags.freq                 
  FROM tags, concepts, expressions
 WHERE concepts.id = tags.conc_id
   AND expressions.id = concepts.expr_id;

The column id references to the table tags, that, references to another table concepts, which, in turn, references to the table e开发者_Python百科xpressions. Here are the table definitions:

CREATE TABLE expressions(
    id              serial PRIMARY KEY,
    name            text,
    is_dropped      bool DEFAULT FALSE,
    rank            float(53) DEFAULT 0,
    state           text DEFAULT 'never edited',
    UNIQUE(name)
);

CREATE TABLE concepts(
    id              serial PRIMARY KEY,
    expr_id         int NOT NULL,
    descr           text NOT NULL,
    source_id       int,
    equiv_p_id      int,
    equiv_r_id      int,
    equiv_len       int,
    weight          int,
    is_dropped      bool DEFAULT FALSE,
    FOREIGN KEY(expr_id) REFERENCES expressions,
    FOREIGN KEY(source_id),
    FOREIGN KEY(equiv_p_id) REFERENCES concepts,
    FOREIGN KEY(equiv_r_id) REFERENCES concepts,
    UNIQUE(id,equiv_p_id),
    UNIQUE(id,equiv_r_id)
);

CREATE TABLE tags(
    conc_id         int NOT NULL,
    freq            int NOT NULL default 0,                                   
    UNIQUE(conc_id, freq)                                                      
);

The table expressions is also referenced from my view (ctags). I want my function to combine rows of my view, that have equal values in the column name and that refer to rows of the table concepts with equal values of the column equiv_r_id so that these rows are combined only once, the combined row has one (doesn't matter which) of the ids, the value of the column descr is concatenated from the values of the rows being combined, and the row freq contains the sum of the values from the rows being combined. I have no idea how to do it, any help would be appreciated.


Basically, what you describe looks like this:

CREATE FUNCTION f_test()
  RETURNS TABLE(min_id int, name text, all_descr text, sum_freq int) AS
$x$
SELECT min(t.conc_id) -- AS min_id
      ,e.name
      ,string_agg(c.descr, ', ') -- AS all_descr
      ,sum(t.freq) -- AS sum_freq
  FROM tags t
  JOIN concepts c USING (id)
  JOIN expressions e ON e.id = c.expr_id;
-- WHERE e.name IS DISTINCT FROM
$x$
  LANGUAGE sql;

Major points:

  • I ignored the view ctags altogether as it is not needed.
  • You could also write this as View so far, the function wrapper is not necessary.
  • You need PostgreSQL 9.0+ for string_agg(). Else you have to substitute with

    array_to_string(array_agg(c.descr), ', ')

  • The only unclear part is this:

    and that refer to rows of the table concepts with equal values of the column equiv_r_id so that these rows are combined only once

Waht column exactly refers to what column in table concepts?
concepts.equiv_r_id equals what exactly?

If you can clarify that part, I might be able to incorporate it into the solution.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜