您的打包日字符串只有 128 个可能的值(七个插槽和每个插槽的两个可能值意味着 128 个可能性),因此只需生成一个包含所有选项的表并加入该表以获取您的解压字符串。您应该能够很容易地生成这样的表:
packed | unpacked
----------+-----------
'0000000' | ''
'0000001' | 'Saturday'
...
'1000001' | 'Sunday, Saturday'
...
然后,您可以将您的打包日列加入此表packed
并选择unpacked
以获取人类友好的字符串。请记住,有限域上的函数是关联表,如果域很小,那么您可以很容易地将函数实现为表。
如果你必须以艰难的方式去做,那么这将在 8.1 中工作,但它相当可怕,应该让你相信(1)你不应该那样存储你的日子,并且(b)你应该处理这种格式数据库之外。在现实生活中我不会做这样的事情,我只是把它包括在内,因为我想看看我是否能想出一些可以在受限的 8.1 环境中工作的东西。您可能也想尽快升级,8.1 已经很长了,不再受支持。
首先,您需要一个包含日期名称的表来加入:
create table days (num int not null, name varchar(9) not null);
insert into days (num, name) values (1, 'Sunday');
insert into days (num, name) values (2, 'Monday');
insert into days (num, name) values (3, 'Tuesday');
insert into days (num, name) values (4, 'Wednesday');
insert into days (num, name) values (5, 'Thursday');
insert into days (num, name) values (6, 'Friday');
insert into days (num, name) values (7, 'Saturday');
然后是用于将字符串连接在一起的自定义聚合,用逗号分隔:
create function comma_join(t1 text, t2 text) returns text as $$
begin
if t1 is null or t2 is null then
return null;
elseif t1 = '' or t2 = '' then
return t1 || t2;
end if;
return t1 || ', ' || t2;
end;
$$ language plpgsql;
create aggregate group_comma_join(
sfunc = comma_join,
basetype = text,
stype = text,
initcond = ''
);
最后,一个隐藏所有丑陋的解包函数:
create function unpack_days(days_string text) returns text as $$
declare
s text;
begin
select group_comma_join(name)
from (
select name into s
from days d join generate_series(1, 7) n(num) on d.num = n.num
where substr(days_string, n.num, 1) = '1'
) dt;
return s;
end
$$ language plpgsql;
现在你可以这样说:
=> select unpack_days('0111110');
unpack_days
----------------------------------------------
Monday, Tuesday, Wednesday, Thursday, Friday
(1 row)
=> select unpack_days('0000000');
unpack_days
-------------
(1 row)