PostgreSQL 8.1大小写到字符串

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

我有一个数据库,它使用0和1的字符串来表示人员工作计划中的天数。例如,011110表示没有星期天,是星期一-星期五,没有星期六。我想使用SQL将其从数据库中提取出来,最后得到一个类似“周一、周二、周三、周四、周五”的字符串。 这是我所能做到的

   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生成器之间可以得到多少逻辑。