可能查询太复杂了,但它可以满足您的需要:-)
参数: cmd - 只是解析 op 的结构 - 可能的操作表 - 用于将表名从短格式转换为完整格式的 jsonb 对象(可能您的意思是 'b' -> 'bbg' 和 'p' -> 'pulls' 'bp' -> 'bbg_pulls')。我在 9.6 上运行此查询并使用 jsonb。您可以将其更改为 9.3 的 json
WITH q AS (
WITH param AS (
SELECT '[bp2][-1]/[bp5]'::text AS cmd,
'+-/%*'::text AS op,
'{"bp": "bbg_pools"}'::jsonb AS tables
), precmd AS (
SELECT btrim(replace(translate(cmd, '[]', ',,'), ',,', ','), ',') AS precmd
FROM param
), split AS (
SELECT i,
split_part(precmd, ',', i) AS part
FROM (
SELECT generate_series(1, length(precmd) - length(translate(precmd, ',', '')) + 1) AS i,
precmd
FROM precmd
) AS a
) SELECT *,
CASE
WHEN part ~ ('^[' || op || ']$') THEN
' ) ' || part || ' ( '
WHEN tables->>(translate(part, '0123456789', '')) != '' THEN
'select val from '::text || (tables->>(translate(part, '0123456789', '0'))) || ' where id = ' || translate(part, translate(part, '0123456789', '0'), '')
WHEN part ~ '^[-]?[0-9]*$' THEN
' and val_date = (CURRENT_TIMESTAMP + (''' || part|| ' day'')::interval)::date '
ELSE
' ERROR '
END AS res
FROM param, precmd, split
ORDER BY i
)
SELECT 'SELECT (' || string_agg(res, ' ') || ')'
FROM q;
一些解释(为了更好地理解,您可以尝试使用 SELECT * FROM q 运行查询而不是聚合)。
参数 CTE 只是您的参数。在 precmd 我准备 cmd 拆分部分,并在拆分中执行。
此查询的结果是:
SELECT (select val from bbg_pools where id = 2 and val_date = (CURRENT_TIMESTAMP + ('-1 day')::interval)::date ) / ( select val from bbg_pools where id = 5)