2

我有一个数据库,它使用一串 0 和 1 来表示人员工作日程中的天数。例如 0111110 将表示没有星期日,是星期一 - 星期五,没有星期六。我想使用 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”,并且没有其他日子。我试过添加|| 但意识到我不知道如何让它发挥作用。如果可以简化事情,则不需要逗号。请帮忙?

4

2 回答 2

1

您的打包日字符串只有 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)
于 2011-10-23T23:22:40.837 回答
-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
于 2011-10-23T22:55:04.347 回答