我有三张表:
create table id_table (
id integer
);
insert into id_table values (1),(2),(3);
create table alphabet_table (
id integer,
letter text
);
insert into alphabet_table values (1,'a'),(2,'b'),(3,'c');
create table greek_table (
id integer,
letter text
);
insert into greek_table values (1,'alpha'),(2,'beta');
Run Code Online (Sandbox Code Playgroud)
我喜欢创建一个函数,将 id_table 与 id 上的字母表或希腊表连接起来。表的选择取决于函数中指定的输入值。我写:
CREATE OR REPLACE FUNCTION choose_letters(letter_type text)
RETURNS table (id integer,letter text) AS $$
BEGIN
RETURN QUERY
select t1.id,
case when letter_type = 'alphabet' then t2.letter else t3.letter end as letter
from id_table t1,
alphabet_table t2 ,
greek_table t3
where t1.id = t2.id and t1.id = t3.id;
END;
$$LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
我跑了select choose_letter('alphabet')。这段代码的问题在于,当 id_table 与alphabet_table 连接时,它没有选择id,没有3。似乎对alphabet_table 和greek_table 都进行了内部连接(所以它只选择了公共ID,1 和2)。为了避免这个问题,我写道:
CREATE OR REPLACE FUNCTION choose_letters(letter_type text)
RETURNS table (id integer, letter text) AS $$
BEGIN
RETURN QUERY
select t1.id,
case when letter_type = 'alphabet' then t2.letter else t3.letter end as letter
from id_table t1
left join alphabet_table t2 on t1.id=t2.id
left join greek_table t3 on t1.id=t3.id
where t2.letter is not null or t3.letter is not null;
END;
$$LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
现在,当 id_table 和alphabet_table 连接时,它会获取所有 3 个 id。但是,当我跑select choose_letter('greek'). 身份证号码 尽管我t3.letter is not null在 where 子句中指定了事实,但 3 在字母列中出现空值。
我正在寻找的是,当我运行时select choose_letters('alphabet'),输出需要是 (1,'a'), (2,'b'),(3,'c')。select choose_letters('greek')应该产生 (1,'alpha'),(2,'beta)。没有缺失值或空值。我怎样才能做到这一点?
学习使用正确、明确的JOIN语法。简单规则: 永远不要在FROM子句中使用逗号。
你可以做你想做的事LEFT JOIN和其他一些逻辑:
select i.id,
coalesce(a.letter, g.letter) as letter
from id_table i left join
alphabet_table a
on i.id = a.id and letter_type = 'alphabet' left join
greek_table g
on i.id = g.id and letter_type <> 'alphabet'
where a.id is not null or g.id is not null;
Run Code Online (Sandbox Code Playgroud)
使用条件letter_type需要在on子句中。否则,alphabet_table总会有一场比赛。
| 归档时间: |
|
| 查看次数: |
9938 次 |
| 最近记录: |