年の各月のカレンダーイベントの数を数える

問題文:

年の各月のイベントの数を表示します。



各イベントには2つのフィールドがあります

-start_date-イベントの開始日

-end_date-イベント完了日



カレンダーイベントのラベル構造:

CREATE TABLE `events` (

`id` int (11) unsigned NOT NULL auto_increment,

`start_date` date default NULL ,

`end_date` date default NULL ,

`created` datetime default NULL ,

`modified` datetime default NULL ,

PRIMARY KEY (`id`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8




* This source code was highlighted with Source Code Highlighter .








期待される結果:

一月 21 2月 34 3月 47
5月 8 6月 12 7月 23
8月 56 九月 11 10月 35
11月 34 12月 24




可能なオプション:



-MONTH(開始日)= MONTH(終了日)、YEAR(開始日)= YEAR(終了日);

イベントは、1年の同じ月に開始および終了します。



-MONTH(開始日)<MONTH(終了日)、YEAR(開始日)= YEAR(終了日);

イベントは1か月で始まり、1年の別の月で終わります。



-MONTH(開始日)= MONTH(終了日)、YEAR(開始日)<YEAR(終了日);

イベントは、同じ月に開始されて終了しますが、異なる年になります(ちょうど1年続きます)。



-MONTH(開始日)<MONTH(終了日)、YEAR(開始日)<YEAR(終了日);

イベントは、異なる年の異なる月に始まり、終わります(12月に始まり、1月に終わります)。



解決策:

この問題を解決するには、2つの方法があります。値を行(各列は月)に表示するか、列(各行はイベント数のある月)に表示します。

JOINに苦しんだ後、結果を文字列に出力することにしました(JOINを使用する場合、イベントの無制限の期間が問題になりました)。 つまり、額の問題を解決し、年ごとにイベントを制限し、このイベントが発生する月を確認することにしました。 エントリを確認するために、MYSQL関数が作成されました。



実装:

DELIMITER $$



DROP FUNCTION IF EXISTS `isEventInMonth`$$



CREATE FUNCTION `isEventInMonth`(

startdate DATE ,

enddate DATE ,

_month INT (1),

_year INT (1)

) RETURNS INT (1)

BEGIN

DECLARE results INT (1);



IF YEAR (startdate) = YEAR (enddate) THEN

SET results = IF ( MONTH (startdate) = _month

AND MONTH (enddate) = _month

OR

( MONTH (startdate) <> MONTH (enddate)

AND ( MONTH (startdate) <= _month

AND MONTH (enddate) >= _month)

)

,1,0);

ELSEIF YEAR (startdate) = _year THEN

SET results = IF ( MONTH (startdate) <= _month ,1,0);

ELSE

SET results = IF ( MONTH (enddate) >= _month ,1,0);

END IF ;



RETURN results;

END $$



DELIMITER ;




* This source code was highlighted with Source Code Highlighter .








この入力関数は、イベントの開始日、イベントの終了日、確認が必要な月と年を受け取り、結果として0または1を返します。つまり、関数は現在の月がイベントの開始と終了の間隔にあるかどうかを確認します。



使用法:



SELECT

SUM (isEventInMonth(start_date,end_date,1,2011)) AS jan,

SUM (isEventInMonth(start_date,end_date,2,2011)) AS feb,

SUM (isEventInMonth(start_date,end_date,3,2011)) AS mar,

SUM (isEventInMonth(start_date,end_date,4,2011)) AS apr,

SUM (isEventInMonth(start_date,end_date,5,2011)) AS may,

SUM (isEventInMonth(start_date,end_date,6,2011)) AS jun,

SUM (isEventInMonth(start_date,end_date,7,2011)) AS jul,

SUM (isEventInMonth(start_date,end_date,8,2011)) AS aug,

SUM (isEventInMonth(start_date,end_date,9,2011)) AS sep,

SUM (isEventInMonth(start_date,end_date,10,2011)) AS 'oct' ,

SUM (isEventInMonth(start_date,end_date,11,2011)) AS nov,

SUM (isEventInMonth(start_date,end_date,12,2011)) AS 'dec'

FROM EVENTS WHERE YEAR (start_date) = 2011 OR YEAR (end_date) = 2011




* This source code was highlighted with Source Code Highlighter .








結果は行になり、各列には特定の年の月ごとのイベント数が表示されます。



要約すると:

実装はエレガントなふりをしません。誰かがイベントカレンダーなどの標準機能を実装すると便利だと思うでしょう。

質問や改善を歓迎します。

PS。 ラベルのタイトルと説明のフィールドを探してはいけません-これらは翻訳可能なフィールドであり、この表にはありません。



UPD:



ユーザーxtenderは、問題に対するより適切な解決策を提案しました。



SELECT <br>

sum ( CASE when t.`start_date`< '2010-02-01' and t.end_date>= '2010-01-01' then 1 else 0 end ) AS jan,<br>

sum ( CASE when t.`start_date`< '2010-03-01' and t.end_date>= '2010-02-01' then 1 else 0 end ) AS feb,<br>

sum ( CASE when t.`start_date`< '2010-04-01' and t.end_date>= '2010-03-01' then 1 else 0 end ) AS mar,<br>

sum ( CASE when t.`start_date`< '2010-05-01' and t.end_date>= '2010-04-01' then 1 else 0 end ) AS apr,<br>

sum ( CASE when t.`start_date`< '2010-06-01' and t.end_date>= '2010-05-01' then 1 else 0 end ) AS may,<br>

sum ( CASE when t.`start_date`< '2010-07-01' and t.end_date>= '2010-06-01' then 1 else 0 end ) AS jun,<br>

sum ( CASE when t.`start_date`< '2010-08-01' and t.end_date>= '2010-07-01' then 1 else 0 end ) AS jul,<br>

sum ( CASE when t.`start_date`< '2010-09-01' and t.end_date>= '2010-08-01' then 1 else 0 end ) AS aug,<br>

sum ( CASE when t.`start_date`< '2010-10-01' and t.end_date>= '2010-09-01' then 1 else 0 end ) AS sep,<br>

sum ( CASE when t.`start_date`< '2010-11-01' and t.end_date>= '2010-10-01' then 1 else 0 end ) AS oct,<br>

sum ( CASE when t.`start_date`< '2010-12-01' and t.end_date>= '2010-11-01' then 1 else 0 end ) AS nov,<br>

sum ( CASE when t.`start_date`< '2011-01-01' and t.end_date>= '2010-12-01' then 1 else 0 end ) AS dec <br>

FROM events t
<br>

<br>

* This source code was highlighted with Source Code Highlighter .







All Articles