Come esercizio di selezione ho ricevuto l'export grezzo dell'ATS di una scale-up HR tech: quasi 10.000 candidature su 7 ruoli, da gennaio 2025 a giugno 2026. La domanda era semplice: cosa funziona e cosa no nel processo di selezione?
Prima di rispondere ho dovuto sistemare i dati. Il 43% delle righe aveva almeno un problema: ruoli scritti in due modi, date con giorno e mese invertiti, bocciature registrate come ritiri, nessun ID candidato. Senza pulizia i due processi più grandi sarebbero risultati divisi a metà.
Ho usato l'AI per una prima lettura del file. Poi ho rifatto io, in SQL Server, la pulizia e i calcoli chiave, e li ho confrontati con l'analisi in Excel: un numero entra nel racconto solo quando i due strumenti danno lo stesso risultato. Una regola mi ha accompagnato dall'inizio: le colonne originali non si toccano, ogni correzione va in una colonna nuova, così ogni anomalia resta tracciabile fino all'origine.
I risultati e il funnel che proporrei, raccontati sulla dashboard in pochi minuti.
Cosa ho trovato
Scegli un tema: grafico, lettura e cosa cambierei.
Esplora il funnel per ruolo
Solo processi chiusi. Ogni barra è uno step: chi passa, chi viene bocciato, chi si ritira.
| Step | Entrati | Passa | Ritiro |
|---|
Il funnel che propongo
Meno step, ognuno con uno scopo, un criterio e un tempo massimo.
Candidatura + knock-out
Lingua, sede, disponibilità, RAL: domande sì/no automatiche.
immediatoScreening CV o portfolio
Scorecard con 3 criteri, scala 1–4 descritta, passa con 3 o più.
3 gg lavorativiCall di 20 minuti
Motivazione, aspettative economiche e tempi, allineate prima di investire colloqui.
entro 5 ggTask breve o test tecnico
Massimo 3 ore, rubrica con soglia. Per i designer un case study, per gli engineer un test asincrono.
correzione 48 hColloquio competenze
Con l'hiring manager, sul task e con la stessa rubrica: il voto motiva la decisione.
feedback 48 hColloquio finale
Team o founder, due valutatori, una sola volta. Sostituisce Interview 2 e 3.
feedback 48 hOfferta
Già allineata dalla call iniziale, inviata subito dopo il colloquio finale.
entro 48 h
Dati: export ATS di una scale-up HR tech (dati fittizi forniti per la selezione). Coorte chiusa = candidature 2025, tutte concluse; coorte aperta = candidature 2026, tutte ancora attive. Mediane dei tempi calcolate escludendo 353 righe con data di fine precedente alla candidatura. Analisi in SQL Server (script 01–03) ed Excel.
Insieme alla dashboard ho consegnato tre script SQL commentati, dall'importazione alla verifica dei numeri. Qui sotto i tre passaggi più significativi.
1. Correggere solo le date sbagliate
Excel aveva già convertito una parte delle date leggendole come mese/giorno. In Excel ho marcato quelle celle con un flag, prima di qualsiasi modifica; in SQL inverto giorno e mese solo dove il flag vale 1.
-- In Excel, prima di toccare le date: FlagIn = SE(VAL.NUMERO(C2);1;0)
-- 1 = cella che Excel aveva già trasformato in data (giorno e mese invertiti)
UPDATE dbo.[ATS Data]
SET DataIn = DATEFROMPARTS(YEAR(DataIn), DAY(DataIn), MONTH(DataIn))
WHERE FlagIn = 1; -- 3951 righe interessate
UPDATE dbo.[ATS Data]
SET DataOut = DATEFROMPARTS(YEAR(DataOut), DAY(DataOut), MONTH(DataOut))
WHERE FlagOut = 1; -- 3528 righe interessate
2. Il funnel per ruolo e step
Solo i processi chiusi: per ogni step conto chi ci è arrivato, chi è passato oltre e come sono finiti gli altri. Il numero dello step viene da una tabella di riferimento, perché ogni ruolo ha un percorso diverso.
WITH chiusi AS (
SELECT * FROM dbo.[ATS Data] WHERE Status_Pulito <> 'Active'
)
SELECT o.Ruolo, o.N_Step, o.Step,
SUM(CASE WHEN c.N_Step >= o.N_Step THEN 1 ELSE 0 END) AS entrati,
SUM(CASE WHEN c.N_Step > o.N_Step THEN 1 ELSE 0 END) AS passati,
SUM(CASE WHEN c.N_Step = o.N_Step AND c.Status_Pulito = 'Rejected' THEN 1 ELSE 0 END) AS rifiutati,
SUM(CASE WHEN c.N_Step = o.N_Step AND c.Status_Pulito = 'Dropped' THEN 1 ELSE 0 END) AS ritirati,
SUM(CASE WHEN c.N_Step = o.N_Step AND c.Status_Pulito = 'Hired' THEN 1 ELSE 0 END) AS assunti,
CAST(100.0 * SUM(CASE WHEN c.N_Step > o.N_Step THEN 1 ELSE 0 END)
/ NULLIF(SUM(CASE WHEN c.N_Step >= o.N_Step THEN 1 ELSE 0 END), 0) AS DECIMAL(5,1)) AS pass_rate_pct
FROM dbo.Ordine_Step o
JOIN chiusi c ON c.Ruolo_Pulito = o.Ruolo
WHERE o.Step <> 'Call con team'
GROUP BY o.Ruolo, o.N_Step, o.Step
ORDER BY o.Ruolo, o.N_Step;
3. Il voto spiega la decisione?
Per ogni step confronto il voto medio di chi passa con quello di chi viene bocciato. Se le due medie coincidono, la decisione è stata presa fuori dal voto.
WITH valutati AS (
SELECT o.Ruolo, o.N_Step, o.Step,
CASE o.Col_Voto
WHEN 'Val_CV' THEN a.Val_CV
WHEN 'Val_Task' THEN a.Val_Task
WHEN 'Val_Int1' THEN a.Val_Int1
WHEN 'Val_Int2' THEN a.Val_Int2
WHEN 'Val_Int3' THEN a.Val_Int3
END AS voto,
CASE WHEN a.N_Step > o.N_Step THEN 1 ELSE 0 END AS passato
FROM dbo.Ordine_Step o
JOIN dbo.[ATS Data] a ON a.Ruolo_Pulito = o.Ruolo
WHERE o.Col_Voto IS NOT NULL
AND o.Step <> 'Call con team'
AND a.Status_Pulito <> 'Active'
AND (a.N_Step > o.N_Step
OR (a.N_Step = o.N_Step AND a.Status_Pulito = 'Rejected'))
)
SELECT Ruolo, N_Step, Step,
COUNT(*) AS valutati,
CAST(AVG(CASE WHEN passato = 1 THEN voto * 1.0 END) AS DECIMAL(3,2)) AS media_passati,
CAST(AVG(CASE WHEN passato = 0 THEN voto * 1.0 END) AS DECIMAL(3,2)) AS media_bocciati,
SUM(CASE WHEN passato = 0 AND voto >= 4 THEN 1 ELSE 0 END) AS bocciati_con_4_5,
SUM(CASE WHEN passato = 1 AND voto <= 2 THEN 1 ELSE 0 END) AS passati_con_1_2
FROM valutati
WHERE voto IS NOT NULL
GROUP BY Ruolo, N_Step, Step
ORDER BY Ruolo, N_Step;
-- Screening Software Engineer: passati 2,95 / bocciati 2,90 -> il voto CV non conta
-- Tech Interview SWE: passati 3,76 / bocciati 3,76 -> si decide fuori dal voto
- Il tentativo sbagliato sulle date è stato il più utile. La prima idea era una funzione SQL che riconoscesse le date invertite dal formato del testo. Non ha funzionato: nel CSV tutte le date erano uscite nello stesso formato, e l'informazione “questa cella era già una data” si era persa nell'esportazione. Una query di controllo sulle lunghezze lo ha dimostrato. Da lì la soluzione: marcare il dato dove l'informazione è ancora visibile, cioè in Excel, e correggere in SQL solo le righe marcate.
- Prima pulire, poi analizzare. Senza unificare i ruoli, i due processi più grandi sarebbero risultati divisi a metà; senza correggere gli status, il Web Designer sarebbe sembrato un problema di abbandoni, mentre il suo task boccia 2 candidati su 3.
- Un numero, due strumenti. Rifare i calcoli chiave in SQL e confrontarli con Excel richiede più tempo, ma è quello che permette di presentare un risultato senza dubbi. L'AI mi ha aiutato a partire in fretta; la verifica l'ho tenuta per me.
Aiuto le aziende a pulire i dati e a costruire dashboard e report che si possono verificare, numero per numero. Se hai un export che non torna, raccontamelo.