4) $quarter = 1; // Calculate start and end dates for the quarter $p_fr_dt = $year . '-' . sprintf('%02d', ($quarter - 1) * 3 + 1) . '-01'; $p_to_dt = date('Y-m-t', strtotime($year . '-' . sprintf('%02d', $quarter * 3) . '-01')); $p_fr_dt_full = $p_fr_dt . ' 00:00:00'; $p_to_dt_full = $p_to_dt . ' 23:59:59'; $response = [ 'success' => true, 'data' => [] ]; try { // 1. 전체학습자(quarter_qty) $stmt_q1 = $pdo->prepare(" SELECT COUNT(*) as quarter_qty FROM edu_users WHERE join_date <= ? AND (end_date >= ? OR end_date IS NULL) "); $stmt_q1->execute([$p_to_dt_full, $p_fr_dt_full]); $quarter_qty = (int) $stmt_q1->fetchColumn(); // 2. 목표선택자(goals_qty) $stmt_q2 = $pdo->prepare(" SELECT COUNT(b.member_id) as goals_qty FROM edu_learning_goals a JOIN edu_user_learning_goals b ON a.goal_code = b.goal_code WHERE 1=1 AND b.is_active = '1' AND a.base_year = ? AND RIGHT(a.quarter, 1) = ? "); $stmt_q2->execute([$year, $quarter]); $goals_qty = (int) $stmt_q2->fetchColumn(); // 3. 목표달성자(goals_completed_qty) $stmt_q3 = $pdo->prepare(" SELECT COUNT( b.member_id) as goals_completed_qty FROM edu_learning_goals a JOIN edu_user_learning_goals b ON a.goal_code = b.goal_code WHERE a.base_year = ? AND RIGHT(a.quarter, 1) = ? AND b.completed_date IS NOT NULL "); $stmt_q3->execute([$year, $quarter]); $goals_completed_qty = (int) $stmt_q3->fetchColumn(); // 4. 목표별선택률 $stmt_q4 = $pdo->prepare(" SELECT a.sort_order , a.title , IFNULL(b.goal_qty, 0) as goal_qty FROM edu_learning_goals a LEFT JOIN ( SELECT goal_code , COUNT(0) AS goal_qty FROM edu_user_learning_goals a WHERE 1=1 AND is_active = '1' AND RIGHT(a.quarter, 1) = ? GROUP BY goal_code) b ON a.goal_code = b.goal_code WHERE 1=1 AND a.is_active = '1' AND RIGHT(a.quarter, 1) = ? ORDER BY a.sort_order "); $stmt_q4->execute([$quarter, $quarter]); $goal_selection_rate = $stmt_q4->fetchAll(PDO::FETCH_ASSOC); // 5. 법인별 비교 $stmt_q5 = $pdo->prepare(" SELECT fn_get_code_name(CONCAT('CO100', a.code)) AS comp_name , IFNULL(b.comp_qty,0) AS comp_qty , COUNT(DISTINCT u.member_id) as all_qty FROM edu_codes a LEFT JOIN edu_users u ON a.code = u.sys_comp_code AND (u.end_date >= ? OR u.end_date IS NULL) LEFT JOIN ( SELECT sys_comp_code , COUNT(0) AS comp_qty FROM edu_user_learning_goals x WHERE 1=1 AND is_active = '1' AND RIGHT(x.quarter, 1) = ? GROUP BY sys_comp_code ) b ON a.code = b.sys_comp_code WHERE 1=1 AND a.group_code = 'CO100' GROUP BY a.code, fn_get_code_name(CONCAT('CO100', a.code)), b.comp_qty ORDER BY a.code "); $stmt_q5->execute([$p_fr_dt_full, $quarter]); $comp_selection_rate = $stmt_q5->fetchAll(PDO::FETCH_ASSOC); // Calculate derived metrics based on User's explicit formulas $target_rate = $quarter_qty > 0 ? round(($goals_qty / $quarter_qty) * 100) : 0; $achieve_rate = $goals_qty > 0 ? round(($goals_completed_qty / $goals_qty) * 100) : 0; $unselected_qty = $quarter_qty - $goals_qty; $unselected_rate = $quarter_qty > 0 ? round(($unselected_qty / $quarter_qty) * 100, 1) : 0; $response['data'] = [ 'kpi' => [ 'quarter_qty' => $quarter_qty, 'goals_qty' => $goals_qty, 'goals_completed_qty' => $goals_completed_qty, 'target_rate' => $target_rate, 'achieve_rate' => $achieve_rate, 'unselected_qty' => $unselected_qty, 'unselected_rate' => $unselected_rate ], 'goals' => $goal_selection_rate, 'comps' => $comp_selection_rate ]; } catch (PDOException $e) { $response['success'] = false; $response['error'] = 'DB Query Error: ' . $e->getMessage(); } catch (Exception $e) { $response['success'] = false; $response['error'] = 'Error: ' . $e->getMessage(); } echo json_encode($response, JSON_UNESCAPED_UNICODE);