我需要使用地图根据值year
为year_code
分配特定值。目前我有一个很大的if语句,显然很难维护。
IF year_code = 'Y' THEN year := 2000; END IF;
IF year_code = '1' THEN year := 2001; END IF;
IF year_code = '2' THEN year := 2002; END IF;
-- and so on
显而易见的解决方案是使用表并选择一个值,但是为了快速完成它,我已被指示将其全部保留在一个postgres函数中。后来我计划将所有这些存储在表格中。
那么有没有办法可以创建临时地图并选择形式来获取年份的价值。真的,我只想清理这个丑陋的代码。感谢。
答案 0 :(得分:12)
在您的函数中使用Common Table Expression (CTE)可以轻松地在以后用基表替换CTE,例如
WITH YearCodes (year_code, year) AS
( SELECT year_code, year
FROM ( VALUES ( 'Y', 2000 ),
( '1', 2001 ),
( '2', 2002 ) )
AS YearCodes ( year_code, year ) )
SELECT ...;
或者,派生表:
SELECT *
FROM ( VALUES ( 'Y', 2000 ),
( '1', 2001 ),
( '2', 2002 ) )
AS YearCodes ( year_code, year )
-- other stuff here;
也许后面的基表可能是calendar table。
答案 1 :(得分:4)
快速而肮脏的解决方案将是一个很难看的CASE声明:
CASE year_code
WHEN 'Y' THEN year := 2000
WHEN '1' THEN year := 2001
-- ...
ELSE year := NULL -- Or something else that makes sense or will
-- blow up so you know something is wrong.
END CASE;
我不知道这是否比一堆丑陋的IF更好。
你可以使用临时表,但是你必须在某处存储大量丑陋的数据,你必须检查临时表是否已经存在并填充它,如果不存在的话。
你说你没有安装hstore
你可以使用PostgreSQL数组和WHILE循环伪造它:
-- Untested "off the top of my head" code
array := ARRAY['Y', '2000', '1', '2001', /* ... */ ];
i := 1;
WHILE i <= array_length(array) LOOP
IF year_code = array[i] THEN
year := array[i + 1]::INTEGER;
EXIT; -- Found it so bust out of the loop.
ELSE
i := i + 2;
END IF;
END LOOP;
我想这是一个你想要的丑陋黑客的问题。
答案 2 :(得分:3)
我建议你创建一个临时表并用你的数据填充它。然后,您可以链接表并转换数据。虽然对于一个SQL语句来说这可能看起来很多,并且可能有更快的方法,但是当您准备创建单独的表时,这将很好地为您设置。然后,您可以删除临时表语句和INSERT语句,只需将要链接的表名从临时表更改为新创建的表。
我看到的唯一另一个相当干净的解决方案是转换数据而不是使用If语句。例如,如果2000年是唯一的一个字母,你可以做一个if语句,如果它是Y(并转换它)而另一个是如果它不是Y,那么年份是2000 + year_code 。如果你的年龄相匹配,那么现在就做一个相当简单的做事方式。
答案 3 :(得分:0)
我偏爱对象映射,可以通过JSON完成。
您可以忽略CTE(带有)。我只包括了它,因此可以独立测试,而无需year_code
列。
WITH ref AS (SELECT '1' AS year_code)
-- This is the only part you need
SELECT COALESCE(
(
(json_build_object(
'Y', 2000,
'1', 2001,
'2', 2001
)::jsonb
)->>(year_code::text))::integer,
2000
)
-- END of the only part you need ;)
FROM ref;
-- RETURNS 2001