SQL, Pandas et IA : Qui excelle vraiment en analytique ?

Le brief IA que les pros lisent chaque soir
Les 7 actus IA du jour, décryptées en 5 min. Gratuit.
Inclus dès l'inscription : notre sélection des meilleurs guides & comparatifs IA.
Choisis ton rythme
Gratuit · Pas de spam · Désabonnement en 1 clic
SQL, Pandas et IA : Qui excelle vraiment en analytique ?
L'analyse de données est un domaine en constante évolution, et choisir le bon outil pour le travail peut être crucial. Pour évaluer l'efficacité de différents outils, une étude a été menée en posant les mêmes trois questions d'entretien de StrataScratch à trois acteurs majeurs : SQL, Pandas, et un agent IA nommé Claude. Chaque solution a été testée sur le même ensemble de données, et les temps d'exécution ont été calculés comme la médiane de 500 exécutions. Les réponses de l'agent Claude ont été générées en réponse à un prompt spécifique, garantissant ainsi une comparaison équitable.
Cette étude a évalué les outils sur huit dimensions essentielles : vitesse, précision, explicabilité, débogage, scalabilité, flexibilité, risque d'hallucination, et préparation à la production. Les questions posées variaient en difficulté, allant de facile à difficile, permettant ainsi de mettre en lumière les différences entre SQL, Pandas et l'agent IA.
Méthodologie de l'étude
Les questions utilisées pour cette comparaison provenaient de la banque d'entretien de StrataScratch, couvrant trois niveaux de difficulté : facile, moyen et difficile. SQL a été exécuté sur SQLite en mémoire, avec des mesures de temps prises sur 500 exécutions pour obtenir une médiane. Pandas a été utilisé avec Python 3.12 sur le même ensemble de données, également mesuré sur 500 exécutions. L'agent IA, Claude's claude-sonnet-4-6, a été sollicité via l'API Anthropic.
Pour chaque question, un prompt utilisateur spécifique a été créé, incluant les noms de table, les noms de colonnes et quelques exemples de lignes. Le prompt système est resté constant pour les trois appels, et les temps de réponse de l'agent ont été mesurés depuis l'envoi de la requête jusqu'à la réception du premier jeton.
Récupération simple : Un consensus entre les outils
La première question d'entretien, posée par Meta, demandait de trouver chaque utilisateur ayant effectué au moins un événement scroll_up et de retourner les identifiants d'utilisateur distincts. Les données étaient contenues dans une seule table, facebook_web_log.
Voici un aperçu de la table facebook_web_log :
2019-04-25 13:30:15
2019-04-25 13:30:18
2019-04-25 13:30:40
2019-04-25 13:30:45
2019-04-25 13:30:40
- Solution SQL (0.002 ms)
SELECT DISTINCT user_id
FROM facebook_web_log
WHERE action = 'scroll_up';
- Solution Pandas (0.40 ms)
import pandas as pd
facebook_web_log[facebook_web_log['action'] == 'scroll_up'].drop_duplicates(subset='user_id')[['user_id']]
Table : facebook_web_log (user_id INTEGER, action TEXT, timestamp TEXT)
(1, 'scroll_up', '2019-01-01 00:00:00')
(2, 'scroll_down', '2019-01-01 00:01:00')
(3, 'like', '2019-01-01 00:03:00')
(2, 'scroll_up', '2019-01-01 00:04:00')
Question : Trouvez tous les utilisateurs ayant effectué au moins un événement scroll_up. Retournez les identifiants d'utilisateur distincts.
- Sortie de l'agent (2 s)
SELECT DISTINCT user_id
FROM facebook_web_log
WHERE action = 'scroll_up';
Sortie : Les trois outils ont retourné les utilisateurs 1 et 2.
Pour ce problème simple de filtrage, l'agent IA a produit une solution identique à celle de SQL. Le principal risque à ce niveau de difficulté réside dans la nomination des colonnes. Sans le schéma dans le prompt, des erreurs de nommage pourraient survenir, entraînant des résultats incorrects sans générer d'erreur explicite.
Agrégation multi-étapes : L'importance de l'ancrage dans le schéma
La deuxième question portait sur l'achèvement des fonctionnalités d'un produit. Une application suivait la progression de chaque utilisateur dans un ensemble de fonctionnalités, chaque fonctionnalité ayant un nombre fixe d'étapes. La tâche consistait à calculer le pourcentage moyen d'achèvement pour chaque fonctionnalité parmi tous les utilisateurs, en tenant compte des utilisateurs qui n'ont jamais commencé une fonctionnalité, comptés comme 0 % d'achèvement.
Deux tables étaient utilisées : facebook_product_features et facebook_product_features_realizations.
2019-03-11 17:15:00
2019-03-11 17:22:00
2019-03-11 17:25:00
2019-03-11 17:27:00
2019-04-05 13:00:07
- Solution SQL (0.007 ms)
WITH max_step AS (
SELECT feature_id, user_id, MAX(step_reached) AS max_step_reached
FROM facebook_product_features_realizations
GROUP BY feature_id, user_id
), calc_per_feature AS (
SELECT feats.feature_id,
max_step_reached,
COALESCE(max_step_reached, 0) * 1.0 / n_steps AS share_of_completion
FROM facebook_product_features feats
LEFT OUTER JOIN max_step
ON feats.feature_id = max_step.feature_id
)
SELECT AVG(share_of_completion) * 100 AS avg_share_of_completion
FROM calc_per_feature
GROUP BY feature_id;
- Solution Pandas (2.05 ms)
import pandas as pd
# max step par utilisateur par fonctionnalité
facebook_product_features_realizations.groupby(['feature_id', 'user_id'])['step_reached']
# jointure avec les fonctionnalités, remplir les utilisateurs qui n'ont jamais commencé avec 0
facebook_product_features,
# pourcentage d'achèvement par ligne utilisateur-fonctionnalité
df['share_of_completion'] = (df['step_reached'] / df['n_steps']) * 100
# moyenne par fonctionnalité
df.groupby('feature_id')['share_of_completion'].to_frame('avg_share_of_completion')
-
facebook_product_features (feature_id INTEGER, n_steps INTEGER)
-
facebook_product_features_realizations (feature_id INTEGER, user_id INTEGER, step_reached INTEGER, timestamp TEXT)
Question : Pour chaque fonctionnalité, calculez le pourcentage moyen d'achèvement parmi tous les utilisateurs. L'achèvement d'un utilisateur = max(step_reached) / n_steps * 100. Les utilisateurs qui n'ont jamais commencé comptent comme 0 % d'achèvement. Retournez : feature_id, avg_share_of_completion.
- Sortie de l'agent (3 s)
WITH user_max_steps AS (
SELECT feature_id, user_id, MAX(step_reached) AS max_step
FROM facebook_product_features_realizations
GROUP BY feature_id, user_id
)
SELECT ROUND(AVG(COALESCE(ums.max_step, 0) * 100.0 / f.n_steps), 2) AS avg_share_of_completion
FROM facebook_product_features f
LEFT JOIN user_max_steps ums ON f.feature_id = ums.feature_id
GROUP BY f.feature_id
ORDER BY f.feature_id;
Sortie : Les trois outils ont produit les mêmes résultats.
L'agent IA a réussi cette tâche grâce à une phrase clé dans le prompt : "Les utilisateurs qui n'ont jamais commencé comptent comme 0 % d'achèvement." Sans cette précision, l'agent aurait pu générer une jointure interne, excluant les non-démarreurs et faussant ainsi les moyennes. Cette erreur est silencieuse, car les chiffres semblent corrects mais sont en réalité inexacts.
Plusieurs tables et logique de fenêtre : Un défi de performance
La troisième question portait sur la consommation d'énergie des centres de données de Meta répartis sur trois régions. Chaque région avait sa propre table : fb_eu_energy, fb_na_energy, et fb_asia_energy. La tâche consistait à combiner ces tables, à sommer la consommation par date, et à produire deux colonnes dérivées : le total cumulé et ce total en pourcentage du total général, arrondi à un nombre entier.
Chaque table régionale avait la même structure.
- Solution SQL (0.010 ms)
WITH total_energy AS (
SELECT recorded_date, consumption FROM fb_eu_energy
UNION ALL
SELECT recorded_date, consumption FROM fb_asia_energy
UNION ALL
SELECT recorded_date, consumption FROM fb_na_energy
), energy_by_date AS (
SELECT recorded_date, SUM(consumption) AS total_energy
FROM total_energy
GROUP BY recorded_date
ORDER BY recorded_date ASC
)
SELECT total_energy,
SUM(total_energy) OVER (ORDER BY recorded_date ASC) AS cumulative_total_energy,
SUM(total_energy) OVER (ORDER BY recorded_date ASC) * 100.0 / (SELECT SUM(total_energy) FROM energy_by_date) AS percentage_of_total_energy
FROM energy_by_date;
- Solution Pandas (1.84 ms)
import pandas as pd
merged_df = pd.concat([fb_eu_energy, fb_asia_energy, fb_na_energy])
energy_by_date = (
merged_df.groupby('recorded_date', as_index=False)['consumption']
.sum()
.sort_values('recorded_date')
)
energy_by_date['cumulative_total_energy'] = energy_by_date['consumption'].cumsum()
energy_by_date['percentage_of_total_energy'] = round(
energy_by_date['cumulative_total_energy'] * 100 / energy_by_date['consumption'].sum()
)
energy_by_date['recorded_date'] = pd.to_datetime(
energy_by_date['recorded_date']
).dt.strftime('%Y-%m-%d')
result = energy_by_date[['recorded_date', 'cumulative_total_energy', 'percentage_of_total_energy']]
-
fb_eu_energy (recorded_date TEXT, consumption INTEGER)
-
fb_na_energy (recorded_date TEXT, consumption INTEGER)
-
fb_asia_energy (recorded_date TEXT, consumption INTEGER)
Question : Combinez toutes les trois tables. Sommez la consommation par date. Sortie :
-
cumulative_total_energy (somme cumulative à travers les dates, ordonnée par date)
-
percentage_of_total_energy (cumulative / total général * 100, arrondi au nombre entier le plus proche)
-
Sortie de l'agent (4 s)
WITH all_energy AS (
SELECT recorded_date, consumption FROM fb_eu_energy
UNION ALL
SELECT recorded_date, consumption FROM fb_na_energy
UNION ALL
SELECT recorded_date, consumption FROM fb_asia_energy
), daily_totals AS (
SELECT recorded_date, SUM(consumption) AS daily_total
FROM all_energy
GROUP BY recorded_date
)
SELECT daily_total,
SUM(daily_total) OVER (ORDER BY recorded_date) AS cumulative_total_energy,
SUM(daily_total) OVER (ORDER BY recorded_date) * 100.0 / SUM(daily_total) OVER () AS percentage_of_total_energy
FROM daily_totals
ORDER BY recorded_date;
Sortie : Les trois outils ont produit la même table.
L'agent IA a utilisé SUM(daily_total) OVER () (une fonction de fenêtre sans ORDER BY) comme dénominateur, contrairement à la sous-requête scalaire de la solution SQL de référence. Les deux approches sont valides, et la sortie était conforme.
Comparaison des performances
À cette échelle de données, SQL a fonctionné en 0.002-0.010 ms, Pandas en 0.4-2.1 ms, tandis que l'agent IA a ajouté 2-4 secondes de temps d'inférence avant que le SQL ne soit exécuté.
L'agent génère d'abord le code, et ce temps de génération représente la latence de bout en bout pour chaque cycle de requête. À l'échelle d'un entrepôt, l'écart se réduit une fois le code généré ; SQL reste plus rapide car il s'exécute à l'intérieur du moteur de base de données, tandis que Pandas atteint un plafond mémoire autour de 10 millions de lignes, nécessitant Apache Spark ou Polars au-delà de cette limite.
Précision et risque d'hallucination
SQL et Pandas sont des outils déterministes. Le même code sur les mêmes données produit toujours la même réponse. Avec des prompts ancrés dans le schéma, Claude a bien répondu aux trois questions, mais chaque appel a généré un SQL différent (noms de CTE différents, alias de colonnes différents, approches différentes mais équivalentes). Sans le schéma, le risque d'hallucination augmente rapidement.
Explicabilité et débogage
Une requête SQL se lit en un seul bloc. Une mauvaise condition de jointure est visible directement dans le texte. Pandas nécessite une certaine maîtrise de Python, mais vous pouvez inspecter le DataFrame à chaque étape. Les agents expliquent leur raisonnement en anglais, puis produisent un code que vous pouvez ou non voir. Si le SQL généré est incorrect, vous suivez une erreur à travers la chaîne de raisonnement d'un modèle plutôt que de lire une requête que vous avez écrite.
Flexibilité et préparation à la production
Pandas est le cle...
Brief IA — L'actualité IA en français
L'essentiel de l'actualité de l'intelligence artificielle, décrypté et expliqué chaque jour.