MySQL
Traiter des données rares ou manquantes
Recherche…
Utilisation de colonnes contenant des valeurs NULL
Dans MySQL et d'autres dialectes SQL, les valeurs NULL
ont des propriétés spéciales.
Considérez le tableau suivant contenant les candidats, les entreprises pour lesquelles ils ont travaillé et la date à laquelle ils ont quitté l'entreprise. NULL
indique qu'un candidat travaille toujours dans l'entreprise:
CREATE TABLE example
(`applicant_id` INT, `company_name` VARCHAR(255), `end_date` DATE);
+--------------+-----------------+------------+
| applicant_id | company_name | end_date |
+--------------+-----------------+------------+
| 1 | Google | NULL |
| 1 | Initech | 2013-01-31 |
| 2 | Woodworking.com | 2016-08-25 |
| 2 | NY Times | 2013-11-10 |
| 3 | NFL.com | 2014-04-13 |
+--------------+-----------------+------------+
Votre tâche consiste à composer une requête qui renvoie toutes les lignes après le 2016-01-01
, y compris les employés travaillant toujours dans une entreprise (ceux dont la date de fin est NULL
). Cette instruction select:
SELECT * FROM example WHERE end_date > '2016-01-01';
ne parvient pas à inclure des lignes avec des valeurs NULL
:
+--------------+-----------------+------------+
| applicant_id | company_name | end_date |
+--------------+-----------------+------------+
| 2 | Woodworking.com | 2016-08-25 |
+--------------+-----------------+------------+
Selon la documentation MySQL , les comparaisons utilisant les opérateurs arithmétiques <,>, = et <> renvoient elles-mêmes NULL
au lieu de booléen TRUE
ou FALSE
. Ainsi, une ligne avec un end_date NULL
n'est ni supérieure à 2016-01-01 ni inférieure à 2016-01-01.
Cela peut être résolu en utilisant les mots-clés IS NULL:
SELECT * FROM example WHERE end_date > '2016-01-01' OR end_date IS NULL;
+--------------+-----------------+------------+
| applicant_id | company_name | end_date |
+--------------+-----------------+------------+
| 1 | Google | NULL |
| 2 | Woodworking.com | 2016-08-25 |
+--------------+-----------------+------------+
Travailler avec des valeurs NULL devient plus complexe lorsque la tâche implique des fonctions d'agrégation telles que MAX()
et une clause GROUP BY
. Si votre tâche consistait à sélectionner la date d'emploi la plus récente pour chaque demandeur_id, la requête suivante semblerait être une première tentative logique:
SELECT applicant_id, MAX(end_date) FROM example GROUP BY applicant_id;
+--------------+---------------+
| applicant_id | MAX(end_date) |
+--------------+---------------+
| 1 | 2013-01-31 |
| 2 | 2016-08-25 |
| 3 | 2014-04-13 |
+--------------+---------------+
Cependant, sachant que NULL
indique qu'un candidat est toujours employé dans une entreprise, la première ligne du résultat est inexacte. L'utilisation de CASE WHEN
fournit une solution de contournement pour le problème NULL
:
SELECT
applicant_id,
CASE WHEN MAX(end_date is null) = 1 THEN 'present' ELSE MAX(end_date) END
max_date
FROM example
GROUP BY applicant_id;
+--------------+------------+
| applicant_id | max_date |
+--------------+------------+
| 1 | present |
| 2 | 2016-08-25 |
| 3 | 2014-04-13 |
+--------------+------------+
Ce résultat peut être renvoyé à l' example
tableau d'origine pour déterminer la société à laquelle un candidat a travaillé en dernier lieu:
SELECT
data.applicant_id,
data.company_name,
data.max_date
FROM (
SELECT
*,
CASE WHEN end_date is null THEN 'present' ELSE end_date END max_date
FROM example
) data
INNER JOIN (
SELECT
applicant_id,
CASE WHEN MAX(end_date is null) = 1 THEN 'present' ELSE MAX(end_date) END max_date
FROM
example
GROUP BY applicant_id
) j
ON data.applicant_id = j.applicant_id AND data.max_date = j.max_date;
+--------------+-----------------+------------+
| applicant_id | company_name | max_date |
+--------------+-----------------+------------+
| 1 | Google | present |
| 2 | Woodworking.com | 2016-08-25 |
| 3 | NFL.com | 2014-04-13 |
+--------------+-----------------+------------+
Ce ne sont que quelques exemples de travail avec des valeurs NULL
dans MySQL.