File size: 3,735 Bytes
e348dc0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
-- === Schémas ===
CREATE SCHEMA IF NOT EXISTS hr_staging;
CREATE SCHEMA IF NOT EXISTS hr;
CREATE SCHEMA IF NOT EXISTS ml;

-- === STAGING : réception brute du CSV (1 ligne = 1 enregistrement brut en JSON line) ===
DROP TABLE IF EXISTS hr_staging.employees_raw;
CREATE TABLE hr_staging.employees_raw (
  row_id      BIGSERIAL PRIMARY KEY,
  raw_line    JSONB NOT NULL,       -- chaque ligne du CSV convertie en JSON (via COPY program/psql \copy depuis CSV)
  loaded_at   TIMESTAMPTZ DEFAULT NOW()
);

-- === TABLE FINALE HR ===
DROP TABLE IF EXISTS hr.employees;
CREATE TABLE hr.employees (
  id                                SERIAL PRIMARY KEY,
  age                               INT NOT NULL CHECK (age BETWEEN 16 AND 100),
  genre                             TEXT NOT NULL,
  revenu_mensuel                    INT NOT NULL CHECK (revenu_mensuel >= 0),
  statut_marital                    TEXT NOT NULL,
  departement                       TEXT NOT NULL,
  poste                             TEXT NOT NULL,
  nombre_experiences_precedentes    INT NOT NULL CHECK (nombre_experiences_precedentes >= 0),
  annees_dans_le_poste_actuel       INT NOT NULL CHECK (annees_dans_le_poste_actuel >= 0),
  note_evaluation_precedente        INT NOT NULL CHECK (note_evaluation_precedente BETWEEN 1 AND 5),
  note_evaluation_actuelle          INT NOT NULL CHECK (note_evaluation_actuelle BETWEEN 1 AND 5),
  heure_supplementaires             INT NOT NULL CHECK (heure_supplementaires IN (0,1)),
  augementation_salaire_precedente  INT NOT NULL CHECK (augementation_salaire_precedente >= 0),
  nombre_participation_pee          INT NOT NULL CHECK (nombre_participation_pee >= 0),
  nb_formations_suivies             INT NOT NULL CHECK (nb_formations_suivies >= 0),
  distance_domicile_travail         INT NOT NULL CHECK (distance_domicile_travail >= 0),
  niveau_education                  INT NOT NULL CHECK (niveau_education BETWEEN 1 AND 5),
  domaine_etude                     TEXT NOT NULL,
  frequence_deplacement             TEXT NOT NULL,
  annees_depuis_la_derniere_promotion INT NOT NULL CHECK (annees_depuis_la_derniere_promotion >= 0),
  annes_sous_responsable_actuel     INT NOT NULL CHECK (annes_sous_responsable_actuel >= 0),
  satisfaction_globale              NUMERIC(5,2) NOT NULL,
  exp_moins_3_years                 SMALLINT NOT NULL CHECK (exp_moins_3_years IN (0,1)),
  attrition                         SMALLINT NOT NULL CHECK (attrition IN (0,1)),
  inserted_at                       TIMESTAMPTZ DEFAULT NOW()
);

-- Index utiles (ex: filtres et agrégations fréquents)
CREATE INDEX IF NOT EXISTS idx_hr_emp_departement ON hr.employees(departement);
CREATE INDEX IF NOT EXISTS idx_hr_emp_attrition   ON hr.employees(attrition);
CREATE INDEX IF NOT EXISTS idx_hr_emp_poste       ON hr.employees(poste);

-- === LOGS D'INFERENCE ML ===
DROP TABLE IF EXISTS ml.predictions_log;
CREATE TABLE ml.predictions_log (
  request_id     UUID PRIMARY KEY,          -- pour tracer chaque appel
  created_at     TIMESTAMPTZ DEFAULT NOW(),
  source         TEXT NOT NULL DEFAULT 'api',  -- api, batch, test...
  input_payload  JSONB NOT NULL,            -- features bruts reçus par l'API
  proba          NUMERIC(10,6),             -- probabilité (nullable si erreur)
  pred           SMALLINT,                  -- classe
  threshold      NUMERIC(6,4),
  model_version  TEXT,                      -- ex: "rf_reg@2025-12-10"
  status         TEXT NOT NULL DEFAULT 'ok',  -- ok / error
  error_message  TEXT                       -- stack / message en cas d'erreur
);

CREATE INDEX IF NOT EXISTS idx_ml_pred_created_at ON ml.predictions_log(created_at);
CREATE INDEX IF NOT EXISTS idx_ml_pred_status     ON ml.predictions_log(status);