使用coalesce改进postgres子查询

时间:2014-09-29 11:29:30

标签: sql postgresql

图片:两个表,案例和case_messages。案例可以包含任意数量的消息或者没有消息。其中一条消息可能是案例中的最终答案。我现在想要返回一个包含bool列的案例列表,告诉我是否有最终答案。如果对于一个案例根本没有消息,则查询应该返回“false”。仅当case_messages中至少有一条相关消息isfinalanswer = true时,查询才返回true。我设法使用coalesce和子查询来处理这个问题,但感觉非常难看:

SELECT cases.id, cases.title,
COALESCE((SELECT isfinalanswer FROM case_messages WHERE caseid = cases.id ORDER BY isfinalanswer DESC LIMIT 1), false) AS hasfinalanswer,
FROM cases;

我该如何改进?

2 个答案:

答案 0 :(得分:2)

我建议使用exists

SELECT c.id, c.title,
       (exists (SELECT 1 FROM case_messages cm WHERE cm.caseid = c.id and isfinalanswer = true)
       ) as hasfinalanswer
FROM cases c;

我不知道你是否会认为这不那么难看。

我应该为性能添加(在问题中没有提到),你需要case_messages(caseid, isfinalanswer)上的索引。有了这样的索引,这可能是最有效的解决方案。

答案 1 :(得分:2)

相关子查询(选择列表上的查询)可能会对性能产生不利影响。执行left joindistinct on

select distinct on (c.id)
    c.id, c.title,
    coalesce(cm.isfinalanswer, false) as hasfinalanswer
from
    cases c
    left join
    case_messages cm on cm.caseid = c.id
order by 1, 3 desc

在这种情况下,coalesce可以替换为is true

    cm.isfinalanswer is true as hasfinalanswer

修改:为避免order by所需的distinct on费用进行预先汇总

select id, title, coalesce(isfinalanswer, false) as hasfinalanswer
from
    cases c
    left join (
        select caseid as id, bool_or(isfinalanswer) as isfinalanswer
        from case_messages
        group by 1
    ) cm using (id)