をカルクするn個の方法のこの1つはそれが保存された機能としてこれを書くために理にかなっています。私は3つの方法を考えることができますが、それぞれ前のものに改善しています(方法2はおそらく十分です)。
方法1:最初の日付から開始し、2番目の日付まで増分します。日付ごとに、DAYOFWEEK()を呼び出します。
select count_days_goal(DATE('2016-03-21'), DATE('2016-03-27'));
select count_days_goal(DATE('2016-03-01'), DATE('2016-03-27'));
これは簡単です:土曜日は、0.5を追加した場合日曜日は、その後0を、追加した場合はそれ以外の場合は1
DROP FUNCTION IF EXISTS `count_days_goal`;
DELIMITER $$
CREATE FUNCTION `count_days_goal`(start_date DATE, end_date DATE) RETURNS FLOAT
DETERMINISTIC
BEGIN
DECLARE sell_days FLOAT;
DECLARE dow INT;
SET sell_days = 0.0;
WHILE start_date <= end_date DO
SET dow = DAYOFWEEK(start_date);
IF (dow > 1) THEN
IF (dow = 7) THEN SET sell_days = sell_days + 0.5;
ELSE SET sell_days = sell_days + 1.0;
END IF;
END IF;
SET start_date = start_date + INTERVAL 1 DAY;
END WHILE;
RETURN (sell_days);
END$$
DELIMITER ;
カップルのテストは、(私の実装は数え日の最後の日が含まれていることに注意してください)を追加それは非効率です。日々離れていくほど時間がかかります。 1つのコールはまだ目の瞬きより速いですが、ほとんどの開発者にとってはやや不快です。幸いにも私たちはより良いことができます。
方法2:各週は5.5営業日です。ですから、日付の間の日数を7で割り、残りは無視し、5.5で複数を除いてください。
例:32日は(4週間+4日)です。これは22営業日に4つの余りを加えたものです。
残っているのは物事が面倒なところです。それらの4日間は土曜日を含むかもしれない、またはそうでないかもしれない。最も簡単な解決策は、最後の数日間方法1を使用することです。 6日以上はループしないので、高速です。
だから今のコードは次のようになります。
DROP FUNCTION IF EXISTS `count_days_goal`;
DELIMITER $$
CREATE FUNCTION `count_days_goal`(start_date DATE, end_date DATE) RETURNS FLOAT
DETERMINISTIC
BEGIN
DECLARE sell_days FLOAT;
DECLARE dow INT;
DECLARE whole_weeks INT;
SET whole_weeks = FLOOR(DATEDIFF(end_date, start_date)/7);
SET start_date = start_date + (7 * whole_weeks);
SET sell_days = whole_weeks * 5.5;
WHILE start_date <= end_date DO
SET dow = DAYOFWEEK(start_date);
IF (dow > 1) THEN
IF (dow = 7) THEN SET sell_days = sell_days + 0.5;
ELSE SET sell_days = sell_days + 1.0;
END IF;
END IF;
SET start_date = start_date + INTERVAL 1 DAY;
END WHILE;
RETURN (sell_days);
END$$
DELIMITER ;
方法3:あなたはまた、完全に方法2を使用しますが、ループを取り除くことができます。それがどのように行われるかを見るには、あなたの前にカレンダーを置くことが役立ちます。 (私はこれを実装するのは苦労しませんでした;方法2はかなり良いです。)
ループの代わりに、最初と最後の日にDAYOFWEEK
を呼び出します。それらをdow_start
とdow_end
と呼ぶことにしましょう。
dow_start < dow_end
の場合、これらの厄介な残りの日はすべて週内にあるため、土曜日から日曜日に折り返されません。だから、すべてを行う必要がある:それらの厄介な残り日数がラップアラウンドん
SET answer = DATEDIFF(dow_end, dow_start) + 1;
IF dow_start = 1 (i.e. Sunday) THEN subtract 1 from answer
IF dow_end is 7 (i.e. Saturday) THEN subtract 0.5 from answer
その後、dow_start > dow_end
場合。その場合、dow_start
とdow_end
を交換することができます(前のケースに戻ります)。前回と同じように計算しますが、5.5から答えを減算して1を加算します。(説明:day_start
とday_end
の間にない曜日を数えてから、週の合計から減算します)
それを書いたりテストしたりしないでください。完全に正しいとは限りません。
銀行休暇の処理方法:テーブル内にある場合は、単にCOUNT
の2つの日付間の行数を使用できます。あなたの答えからそれを引きます。簡単! (銀行休暇は決して週末にはないと仮定します)さまざまな国の銀行休業日をリストするWebサイトもあります。休日テーブルを簡単に作成できるように、今後の予定リストを生成するものもあります。
テーブルの構造は何ですか? DateのMAXを取得すると、その列には何がありますか?すでにDBに何かがあるようですが、あなたがすでに持っているものを知ることは重要です。私は銀行の休暇の問題も持っていると思います... –
「日付」は収入が得られた日です。 MAX( 'Date')は、2016年3月31日を返します。 – czmudzin
テーブルに格納されているデータと何が関係しているのかよくわかりません。 – Strawberry