我经常需要提交几乎相同的查询但是使用不同的参数(单个参数但在SELECT …
子句中多次(不是WHERE
(!)))。
为了说明这一点,它位于duc.opt_level >= 5 /*v_min_level*/
位于下方的每个地方:
SELECT duc.id_du, duc.du_type_cd, duc.du_name, duc.du_addr, duc.id_du_def, duc.def_repeat_flg, defc.allows_txt_flg
,r.lvl + CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN 0 ELSE 1 END ELSE 0 END lvl
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.id_du ELSE duc.id_du END ELSE r.id_du END entid
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.entraw ELSE duc.du_addr END ELSE r.entraw END entraw
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.entnm ELSE duc.du_name END ELSE r.entnm END entnm
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.pentid ELSE r.entid END ELSE r.pentid END pentid
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.pentraw ELSE r.entraw END ELSE r.pentraw END pentraw
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs=1 THEN r.pentnm ELSE r.entnm END ELSE r.pentnm END pentnm
,defc.def_type, defc.val_type
,defc.is_nillable
,defc.optional
FROM r
JOIN data_unit duc
ON duc.id_parent_du = r.id_du
JOIN du_def defc
ON defc.id_du_def = duc.id_du_def
...
Postgres ver。 9.5.1
参数化这个查询的任何优雅方式,所以我只能通过重新定义这个参数来调用它吗?
出现了一些关于匿名PL / pgSQL块的内容,但我不确切知道如何
答案 0 :(得分:0)
您可以交叉加入"值"表:
SELECT duc.id_du, duc.du_type_cd, duc.du_name, duc.du_addr, duc.id_du_def, duc.def_repeat_flg, defc.allows_txt_flg
,r.lvl +
CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= p.min_level AND duc.max_occurs=1 THEN 0 ELSE 1 END ELSE 0 END lvl
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= p.min_level AND duc.max_occurs=1 THEN r.id_du ELSE duc.id_du END ELSE r.id_du END entid
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= p.min_level AND duc.max_occurs=1 THEN r.entraw ELSE duc.du_addr END ELSE r.entraw END entraw
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= p.min_level AND duc.max_occurs=1 THEN r.entnm ELSE duc.du_name END ELSE r.entnm END entnm
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= p.min_level AND duc.max_occurs=1 THEN r.pentid ELSE r.entid END ELSE r.pentid END pentid
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= p.min_level AND duc.max_occurs=1 THEN r.pentraw ELSE r.entraw END ELSE r.pentraw END pentraw
,CASE duc.du_type_cd WHEN 'e' THEN CASE WHEN duc.opt_level >= p.min_level AND duc.max_occurs=1 THEN r.pentnm ELSE r.entnm END ELSE r.pentnm END pentnm
,defc.def_type, defc.val_type
,defc.is_nillable
,defc.optional
FROM ...
cross join (values (5)) as p(min_level)
答案 1 :(得分:0)
假设 所有列都不能为NULL(问题中缺少信息)。
将CASE
表达式解释为:
, CASE WHEN duc.du_type_cd = 'e' AND (duc.opt_level < 5 OR duc.max_occurs <> 1) THEN r.lvl + 1 ELSE r.lvl END AS lvl
, CASE WHEN duc.du_type_cd = 'e' AND (duc.opt_level < 5 OR duc.max_occurs <> 1) THEN duc.id_du ELSE r.id_du END AS entid
, CASE WHEN duc.du_type_cd = 'e' AND (duc.opt_level < 5 OR duc.max_occurs <> 1) THEN duc.du_addr ELSE r.entraw END AS entraw
-- etc.
相同的重复条件可以集中在LEFT JOIN
列表中的r
(r1
}的另一个FROM
个实例中。如果不满足条件,则默认使用COALESCE
的替代值:
SELECT duc.id_du, duc.du_type_cd, duc.du_name, duc.du_addr, duc.id_du_def, duc.def_repeat_flg
, defc.allows_txt_flg, defc.def_type, defc.val_type, defc.is_nillable, defc.optional
, COALESCE(r1.lvl , r.lvl + 1) AS lvl
, COALESCE(r1.id_du , duc.id_du) AS entid
, COALESCE(r1.entraw , duc.du_addr) AS entraw
, COALESCE(r1.entnm , duc.du_name) AS entnm
, COALESCE(r1.pentid , r.entid) AS pentid
, COALESCE(r1.pentraw, r.entraw) AS pentraw
, COALESCE(r1.pentnm , r.entnm) AS pentnm
FROM duc
JOIN defc ON ??? -- missing information
JOIN r ON ??? -- missing information
LEFT JOIN r1 ON duc.du_type_cd <> 'e'
OR (duc.opt_level >= 5 /*v_min_level*/ AND duc.max_occurs = 1);
现在您只提供 v_min_level
一次。查询要短得多。也可能会快一点。
永远不要省略列别名的关键字AS
。 The manual:
省略
AS
关键词
...
在FROM
项中,标准和PostgreSQL都允许省略AS
在作为未保留关键字的别名之前。但这是不切实际的 输出列名称,因为语法含糊不清。