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 の可能な値しかありません (7 つのスロットと各スロットの 2 つの可能な値は 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 に答える