2017-01-29 4 views
1

MySQLの重複するdatetimesの合計に関連するSOに関する提案されたソリューションを評価中です。私は銀色の弾丸の解決策を見つけることができなかったので、クラシック/工業グレードのアルゴリズム手順が利用可能かどうか、あるいはカスタムメイドの開発が必要かどうかを知りたい。MySQLで重複するdatetimesを合計する最も効率的な方法

Graphical representation

合計8時間(4 + 4)であるべきです。 MySQLのスルー

提案された解決策

function final_balance($teacher_id, $aa, $teaching_id=0) { 
    $dbo = $this->Attendance->getDataSource(); 
    $years=$this->Attendance->Student->Year->find('list', array('fields' => array('anno', 'data_from'))); 
    $filteraa='attendances.start>="'.$years[$aa].'"'; 
    $this->query('SET @interval_id = 0'); 
    $this->query('SET @interval_end = \'1970-01-01 00:00:00\''); 
    $sql='SELECT 
     MIN(start) as start, 
     MAX(end) as end 
     FROM (
      SELECT 
       @interval_id := IF(attendances.start > @interval_end, @interval_id + 1, @interval_id) AS interval_id, 
       @interval_end := IF(attendances.start < @interval_end, GREATEST(@interval_end, attendances.end), attendances.end) AS interval_end, 
       attendances.start, 
       attendances.end 
      FROM attendances 
      INNER JOIN attendance_sheets ON (
       attendance_sheet_id = attendance_sheets.id AND 
       attendance_sheets.teacher_id='.$teacher_id.' AND '.$filteraa.' AND 
       attendance_sheet_status_id = 2 AND 
       attendance_status_id!=3'. 
       ($teaching_id?' AND attendances.teaching_id IN ('.$teaching_id.')':'').'      
      ) 
      ORDER BY attendances.start,attendances.end 
     ) intervals GROUP BY interval_id'; 

    // final query to sum in the temp table 
    $finalStatement =array(
     'table' => $dbo->expression('('.$sql.')')->value, 
     'alias' => 'Attendance', 
     'fields' => array(
      'DATE_FORMAT(start, \'%d/%m/%Y\') as data', 
      'DATE_FORMAT(start, \'%m-%Y\') as datamese', 
      'DATE(start) as datasql', 
      $teacher_id.' AS teacher_id', 
      'DAY(start) as giorno', 
      'MONTH(start) as mese', 
      'YEAR(start) as anno', 
      'SEC_TO_TIME(SUM((TIME_TO_SEC(end) - TIME_TO_SEC(start)))) as ore', 
     ), 
     'conditions' => array(), 
     'limit' => null, 
     'group' => array('CONCAT(YEAR(start),MONTH(start))', 'DATE(start) WITH ROLLUP'), 
     'order' => null 
    ); 
    $finalQuery= $dbo->buildStatement($finalStatement, $this->Attendance); 
    return $this->Attendance->query($dbo->expression($finalQuery)->value); 
} 

参照

Sum amount of overlapping datetime ranges in MySQLは、異なるタスクを実行

MySQL: sum time ranges exluding overlapping onesMySQL: sum datetimes without counting overlapping periods twice 状況に応じ

GeeksForCode: Merge Overlapping Intervals

+0

興味のある方は、最後にhttp://www.geeksforgeeks.org/merging-intervals/をMySQLに適用しました。 CakePHPのコードで質問によって更新されました –

答えて

0

すべてのケースを考慮していないように私には思われる、次は、便利で効率的かもしれません両方。

時間あたり1つの行を持つ別のテーブルを作成します。内部はテーブルとテーブルを結合し、新しい列のみを選択して行を削除します。

解像度を引き続き増やすことができます(例:分または秒)が、コードが遅くなることがあります。

+0

ElKaminaさん、あなたがすでに述べたように、ゆっくりと変化するデータや数行で実現可能な解決策です。私が理解しようとしていることは、それが問題に取り組むための共通の問題のように思われる(Cormenのスタイル:D)、問題に対する幅広い文献/ –

関連する問題