映射没有表的值

时间:2011-05-23 05:14:20

标签: sql database postgresql

我需要使用地图根据值yearyear_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函数中。后来我计划将所有这些存储在表格中。

那么有没有办法可以创建临时地图并选择形式来获取年份的价值。真的,我只想清理这个丑陋的代码。感谢。

4 个答案:

答案 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