0

我有 3 张桌子。

Table A   |   Table B   |   Table C
----------|-------------|------------
name      |   name      |   name
phrase    |   phrase    |   phrase
field 1   |   include   |   include
field 2   |   exclude   |   exclude
field 3   |   field 1   |   field 1

表 A、B、C 也包含很多其他列,但我只对Table B (include and exclude)and感兴趣Table C (include and exclude)

我正在尝试编写一个函数,它将表 A 的 和 作为参数,并对表 A 进行查询name,以获取两个表的列,其中和等于参数和。phraseTable BTable CincludeexcludeTable B (name and phrase)Table C (name and phrase)namephrase

include 和 exclude 列是布尔值,我想使用B.include,B.exclude和返回一个字符串。C.includeC.exclude

到目前为止我写的是,但我不确定它是否正确。

CREATE OR REPLACE FUNCTION createString(name text, phrase text) RETURNS table (descp text) AS
$$
BEGIN

    select b.include, b.exclude, c.include, c.exclude
    from (TableB b join TableC c on b.name = c.name and b.phrase = c.phrase)
    where b.name = name and b.phrase = phrase;

    IF b.include = true THEN
        NEW := 'b included';
    ELSEIF b.exclude = true THEN
        NEW := 'b excluded';
    ELSEIF c.exclude = true THEN
        NEW := 'c excluded';
    ELSEIF c.exclude = true THEN
        NEW := 'c excluded';
    END IF;

  RETURN NEW;
END;

$$ LANGUAGE plpgsql;

我是编写函数的新手,我真的不知道我是否做得对。有人可以帮我指出正确的方向。

4

3 回答 3

1

我不建议您为此编写函数。函数往往是性能杀手。

相反,您可以编写一个视图,left join用于将表放在一起:

对于您编写的逻辑,您似乎想要:

select a.*,
       (case when b.include then 'B included' 
             when b.exclude then 'B excluded' 
             when c.include then 'C included' 
             when c.exclude then 'C excluded' 
        end) as string
from a left join
     b
     on a.name = b.name and a.phrase = b.phrase left join
     c
     on a.name = c.name and a.phrase = c.phrase;

这将返回标志上的第一个匹配项。我可能希望您希望以某种方式将字符串连接在一起,但这不是您编写的伪代码。

于 2019-09-04T11:30:45.547 回答
0

我还在学习,我在原始问题中写的是学习和试用代码。我最终写了这样的东西......

CREATE OR REPLACE FUNCTION createString(name text, phrase text) RETURNS TEXT AS
$$
DECLARE
    moInclude boolean;
    moExcluded boolean;
    modaidInclude boolean;
    modaidExclude boolean;
    result text := 'None';
BEGIN
    select mo.include, mo.exclude, modaid.include, modaid.exclude INTO moInclude, moExcluded, modaidInclude, modaidExclude
    from (tableB AS mo JOIN tableC AS modaid on mo.text = modaid.text and mo.phrase = modaid.phrase)
    where mo.text = text and mo.phrase = phrase;

    IF moInclude = true AND modaidInclude = true THEN
        result := 'INCLUDED';
    ELSEIF (moExcluded = true) THEN
        result := 'EXCLUDED';
    ELSEIF ((moInclude = false AND modaidInclude = true AND modaidExclude = false) OR
        (moInclude = false AND modaidInclude = false AND modaidExclude = true) OR
        (moInclude = true AND modaidInclude = false AND modaidExclude = true) OR
        (moInclude = true AND modaidInclude = false AND modaidExclude = false)) THEN
        result := 'PARTIAL';
    ELSE
        result := 'NONE';
    END IF;

RETURN result;
END;
$$ LANGUAGE plpgsql;

创建视图时调用此函数。

谢谢大家的帮助。

于 2019-09-05T15:16:58.843 回答
0

@GordonLinoff 是正确的,仅使用 SQL 而不是函数会更好。但是,如果您必须有一个函数,那么您可以使用语言 sql创建一个 SQL 函数函数。下面将转换您的最后一个函数并将其复制为 SQL 函数。此外,由于列 Include 和 Exclude 已定义为布尔值,因此它们不需要相等的疏散。也就是说,“if include ...”将产生与“if include = true”相同的结果。但是对于假值,您需要否定该值,因此“如果包含 = 假”就变成了简单的“不包含”。我用过,但很容易更换。

-- create tables and gen test data 
create table tableA (name text, phase text, field1 text, field2 text, field3 text) ;
create table TableB (name text, phase text, include boolean, exclude boolean, field1 text);
create table TableC (name text, phase text, include boolean, exclude boolean, field1 text);


insert into tableA (name,phase)
     values ('n1','p1') 
          , ('n2','p1') 
          , ('n3','p1') 
          , ('n4','p1')
          , ('n5','p1')
          , ('n6',null);           

insert into tableB(name, phase, include, exclude)
     values ('n1','p1',true,true)
          , ('n2','p1',true,false)
          , ('n3','p1',false,true)
          , ('n4','p1',false,false)
          , ('n5','p1',false,false);

insert into tableC(name, phase, include, exclude) 
     values ('n1','p1',true,true)
          , ('n2','p1',true,false)
          , ('n3','p1',false,true)
          , ('n4','p1',false,false) 
          , ('n5','p1',true,false);

-------------------------------------------------------------------------------------------------------------
create or replace function createString(name_in text, phase_in text) 
returns text
language sql strict
as $$
    select case when (mo.include and modaid.include)                                     then 'INCLUDED'
                when (mo.exclude)                                                        then 'EXCLUDED'
                when (   (not mo.include and modaid.include and not modaid.exclude)  
                      or (not mo.include and not modaid.include and modaid.exclude) 
                      or (mo.include     and not modaid.include and modaid.exclude) 
                      or (mo.include     and not modaid.include and not modaid.exclude)) then 'PARTIAL'
                else 'NONE' 
            end   
     from tableb as mo 
     join tablec as modaid on (    mo.name  = modaid.name 
                               and mo.phase = modaid.phase
                              )
    where mo.name  = name_in
      and mo.phase = phase_in
$$; 

-------------------------------------------------------------------------------------------------------------
-- test
select name, phase, createString(name, phase) 
  from tableA;  
于 2019-09-06T02:36:56.837 回答