2

関数に問題があります。月の日付、日の名前、およびその月の平日の数を含むテーブルを取得する必要があります。私はすでにここでいくつかの助けを見つけてそれを私のニーズに適合させました、しかし私は関数を実行/コンパイルすることができませんこれは私がこれまでに持っているものです:

create or replace TYPE DATE_ROW AS OBJECT
(
  MyDate DATE,
  Dayname VARCHAR2(12),
  Amount Integer
 )

create or replace TYPE DATE_TABLE as table of DATE_ROW

create or replace FUNCTION myfinaldays (mydate date)
       RETURN DATE_TABLE
       PIPELINED
    IS
       V_MYDATE          DATE;
       V_DAYNAME   VARCHAR2(12);
       V_AMOUNT           NUMBER;
BEGIN
    with this_month as (
        select trunc(to_date('mydate'), 'mm')+level-1 dy
          from dual 
       connect by level < (trunc(add_months(to_date('mydate'),1), 'mm')- trunc(to_date('mydate'), 'mm'))+1
    )
    FOR i IN 0 .. (select count(*) from this_month) LOOP
        select (dy) Daydate,
               to_char(dy, 'day'), Dayname,
              ( select count(*)
                  from this_month 
                 where  to_char(dy, 'dy') not in ('sat', 'sun')
               ) Amount
          from this_month
         where to_char(dy, 'dy') not in ('sat', 'sun')
           and EXTRACT(day from to_date(dy)) = i;

       pipe row (date_row(v_mydate,v_dayname, v_amount));
   END LOOP;
   RETURN;
   END;

その場合、関数呼び出しは次のようになります。

select * from date_table(cast(myfinaldays('01.02.12')));

パラメータとして指定できる日付は1つだけです。

これがゆっくりと私を怒らせているので、誰かがここで私を助けてくれることを願っています。任意のアイデア、例、または考えをいただければ幸いです。

アップデート:

OK、これがmybeのアップデートで、私の問題に対するさらに役立つ情報がいくつかあります。

これは機能しており、私の目的はこれを関数に入れて、1つのパラメーターで呼び出すことができるようにすることです。

    with this_month as (  
    select trunc(to_date('01.02.12'), 'mm')+level-1 dy
    from   dual 
    connect by level < (trunc(add_months(to_date('01.02.12'),1), 'mm')- trunc(to_date('01.02.12'), 'mm'))+1
    )
    select (dy) mydate, (select count(*) from this_month) Days_in_month
    ,      to_char(dy, 'day') Dayname
    ,     ( select count(*) from this_month where  to_char(dy, 'dy') not in ('sat', 'sun') ) Amount
    from   this_month
    where  to_char(dy, 'dy') not in ('sat', 'sun') ;

追加したループの場合:'およびEXTRACT(day from to_date(dy))=i'最後に。

最終的に必要なものがわかるように、日付を追加しました。代わりにmydateを記述し、開発者で実行した後にパラメーターとして01.02.12と入力しても、引き続き機能します。

コンパイル時に発生するエラー:-Error(10,1):PL / SQL:SQLステートメントは無視されます

- Error(15,5): PL/SQL: ORA-00928: Keyword SELECT missing

- Error(22,8): PLS-00113: END-Definer 'LOOP' must complete 'myfinaldays' in row 1, comlumn 10 

- Error(23,4): PLS-00103: Found the symbol "RETURN" 

私のOracleは英語を実行していないため、エラーは翻訳されているので、正しく推測できたと思います。

4

2 に答える 2

2

ここには多くの問題があります。

  • selectで直接使用することはできませんfor i in 1..x(0ではなく1にする必要があります)。ローカル変数を選択して、それを最終値として使用する必要があります。
  • ループwithへの入力として使用することはできません。forただし、以下に示すように、そこでカーソルを使用できます。
  • get no-data-foundのループ内のselectiは、土曜日または日曜日を表します(この場合、2月に実行していると仮定すると、4番目です)。
  • すべての行の週末以外のすべての行の数を取得することは非効率的ですが、そのような少量のデータでは実際には問題ではありません。
  • あなたが参照しているto_date('mydate'); mydateはすでに日付であり、「mydate」はそれに関係のない文字列です。

また、日付の形式やロケールを想定するなど、他のこともあるかもしれません。これは、どこにto_char(x, 'dy')も戻らないsatためsunですが、これは制限された方法で使用されるため、あまり気にしないでください。

あなたが期待している出力を理解しようとすることから、私はこれがうまくいくと思います(days_in_monthあなたが元の質問に追加されるように変更されたタイプで):

create or replace type date_row as object
(
    mydate DATE,
    dayname VARCHAR2(12),
    days_in_month NUMBER,
    amount NUMBER
)
/

create or replace type date_table as table of date_row
/

create or replace function myfinaldays (mydate date)
return date_table pipelined deterministic is
begin
    for r in (
        select *
        from (
            select dy as daydate,
                to_char(dy, 'day') as dayname,
                count(*) over () as days_in_month,
                sum(case when to_char(dy, 'dy') in ('sat', 'sun')
                    then 0 else 1 end) over () as amount
            from (
                select trunc(mydate, 'mm')+level-1 dy
                from dual 
                connect by level < (trunc(add_months(mydate, 1), 'mm')
                    - trunc(mydate, 'mm')) + 1
            )
        )
        where to_char(daydate, 'dy') not in ('sat', 'sun')
    ) loop
       pipe row (date_row(r.daydate, r.dayname, r.days_in_month, r.amount));
    end loop;
end myfinaldays;
/

(必要がない場合は、 /days_in_monthを移動して、の代わりにforを使用できます。アウターは現在曜日にフィルタリングされているため、すべての日をカウントできますが、そうでない場合は問題ありません。その値が必要です)。satsuncountamountsum(case)select

次に、次のように呼び出します。

alter session set nls_date_format = 'DD.MM.RR';
select * from table(myfinaldays(to_date('01.02.12', 'DD.MM.RR')));

MYDATE   DAYNAME      DAYS_IN_MONTH     AMOUNT
-------- ------------ ------------- ----------
01.02.12 wednesday               29         21
02.02.12 thursday                29         21
03.02.12 friday                  29         21
06.02.12 monday                  29         21
...
29.02.12 wednesday               29         21

21 rows selected.
于 2012-09-26T12:57:45.373 に答える
0

関数はテーブル値関数(テーブルを返す)であるため、通常の関数として呼び出すことはできません。あなたはそれに参加しています:

Oracleでは次のようなものです。

select * from date_table t
cross join table( myfinaldays(<t.date colum>)) 
于 2012-09-26T11:31:47.520 に答える