SQL JOIN:在JOIN子句中添加自定义约束

时间:2019-06-28 16:41:19

标签: sql postgresql

我想选择首选语言(如果存在),否则选择默认语言。

SELECT  a.code,
        case
          when vpi.program_items is not null then vpi.program_items  else vpi2.program_items
        end
FROM              activity a                        
                    LEFT OUTER JOIN v_program_items vpi ON vpi.activity_id = a.id AND vpi.language = 'fr_BE'
                    LEFT OUTER JOIN v_program_items vpi2 ON vpi2.activity_id = a.id AND vpi2.language = 'fr'
WHERE   a.id = 62170

v_program_items表如下:

 - ID      | language|  program_items
 - 62170   | fr      |  Présentation du club et des machines¤Briefing avant le vol¤45 minutes de vol en ULM 
 - 62170   |  fr_BE  |  Un vol en ULM (45 min)  

我使用两个JOIN(在同一张表上)和一个CASE / WHEN。
只能使用一个JOIN吗?

2 个答案:

答案 0 :(得分:1)

您的方法很好。如果只需要一个join,则可以这样操作:

SELECT a.code, vpi.program_items
FROM activity a LEFT JOIN
     v_program_items vpi
     ON vpi.activity_id = a.id A
WHERE a.id = 62170 AND vp.language in ('fr_BE', 'fr')
ORDER BY (vp.language = 'fr_BE') DESC
FETCH 1 ROW ONLY;

目前尚不清楚这是否会有更好的性能。

答案 1 :(得分:1)

您拥有的联接很好,并且在索引方面表现很好-应该是UNIQUE索引(或PK):

CREATE UNIQUE INDEX ON v_program_items (activity_id, language);

使用SELECT列表中的COALESCE,例如注释中建议的“ PM 77-1”:

SELECT a.code, COALESCE(v1.program_items, v2.program_items) AS program_items
FROM   activity a                        
LEFT   JOIN v_program_items v1 ON v1.activity_id = a.id AND v1.language = 'fr_BE'
LEFT   JOIN v_program_items v2 ON v2.activity_id = a.id AND v2.language = 'fr'
WHERE  a.id = 62170;

在Postgres 11中,仅当表v_program_items大时,才考虑覆盖索引:

CREATE UNIQUE INDEX ON v_program_items (activity_id, language) INCLUDE (program_items);

相关:

无论哪种方式,当只选择一行(或几行)时,相关性较低的子查询都应该更快。也很简单:

SELECT a.code
     , COALESCE((SELECT program_items FROM v_program_items WHERE activity_id = a.id AND language = 'fr_BE')
              , (SELECT program_items FROM v_program_items WHERE activity_id = a.id AND language = 'fr')) AS program_items
FROM   activity a
WHERE  a.id = 62170