PostgreSQL 8.1大小写到字符串
我有一个数据库,它使用0和1的字符串来表示人员工作计划中的天数。例如,011110表示没有星期天,是星期一-星期五,没有星期六。我想使用SQL将其从数据库中提取出来,最后得到一个类似“周一、周二、周三、周四、周五”的字符串。 这是我所能做到的PostgreSQL 8.1大小写到字符串,postgresql,case,concat,Postgresql,Case,Concat,我有一个数据库,它使用0和1的字符串来表示人员工作计划中的天数。例如,011110表示没有星期天,是星期一-星期五,没有星期六。我想使用SQL将其从数据库中提取出来,最后得到一个类似“周一、周二、周三、周四、周五”的字符串。 这是我所能做到的 CASE WHEN SUBSTR(regular_work_days, 1,1)='1' THEN 'Sunday' WHEN SUBSTR(regular_work_days, 2,1)='1' THEN 'Mon
CASE
WHEN SUBSTR(regular_work_days, 1,1)='1' THEN 'Sunday'
WHEN SUBSTR(regular_work_days, 2,1)='1' THEN 'Monday'
WHEN SUBSTR(regular_work_days, 3,1)='1' THEN 'Tuesday'
WHEN SUBSTR(regular_work_days, 4,1)='1' THEN 'Wednesday'
WHEN SUBSTR(regular_work_days, 5,1)='1' THEN 'Thursday'
WHEN SUBSTR(regular_work_days, 6,1)='1' THEN 'Friday'
WHEN SUBSTR(regular_work_days, 7,1)='1' THEN 'Saturday'
ELSE ' '
END AS "Regular Work Days",
可以预见的是,我的结局是第一个“1”,而不是其他日子。我试着加上| |,但意识到我不知道如何让它起作用。逗号是不必要的,如果它能简化事情的话。
请帮忙?这应该行得通。也许有更简单的方法,但是
select
array_to_string(array_agg(
(regexp_split_to_array('sun,mon,tue,wed,thu,fri,sat', ','))[i]
), ', ')
from generate_series(1, 7) i
where (regexp_split_to_array('0111110', ''))[i] = '1'
这使得:
daylist
-------------------------
mon, tue, wed, thu, fri
这应该行得通。也许有更简单的方法,但是
select
array_to_string(array_agg(
(regexp_split_to_array('sun,mon,tue,wed,thu,fri,sat', ','))[i]
), ', ')
from generate_series(1, 7) i
where (regexp_split_to_array('0111110', ''))[i] = '1'
这使得:
daylist
-------------------------
mon, tue, wed, thu, fri
对于打包的日期字符串,您只有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)
对于打包的日期字符串,您只有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)
在8.1中不起作用,不
array\u agg
或regexp\u split\u to\u array
@muistooshort您可以构建创建自己的array\u agg函数,但不确定将regexp\u split\u设置为_array@vol7ron:您可以构建一个数组\u agg
(有点像我做的MySQL的group_concat
的乱七八糟的版本),但是128行的查找表会容易得多。@muistooshort:啊,是的,我没有注意到“8.1”标题中的一部分。在8.1中不起作用,没有array\u agg
或regexp\u split\u to\u array
@muistooshort您可以创建自己的array\u agg函数,但不确定要创建regexp\u split\u有多容易_array@vol7ron:您可以构建一个数组\u agg
(有点像我做的MySQL的group_concat
的乱七八糟的版本),但是128行的查找表会容易得多。@muistooshort:啊,是的,我没有注意到“8.1”标题中的一部分。啊,完全控制环境。该字段的主要目的是在pdf上勾选复选框,所以我一直在使用它。但是……没有什么能阻止我在存储字符串的表中添加另一个字段星期一、星期二…,以便导出。谢谢大家的思考!@user973828:a lookup在数据库之外的代码中的表是另一种选择,但我不知道在数据库和PDF生成器之间可以得到多少逻辑。啊,完全控制环境。该字段的主要目的是勾选PDF上的复选框,所以我一直在使用它。然而,没有什么可以阻止我在t中添加另一个字段存储字符串的表星期一,星期二…,用于导出。谢谢大家的思考!@user973828:在数据库之外的代码中查找表是另一种选择,但我不知道在数据库和PDF生成器之间可以得到多少逻辑。