Le stockage des données dans une seule colonne est la méthode préférée, car elles sont inextricablement liées. Un point dans le temps est une seule information, pas deux.
Une façon courante de stocker des données de date / heure, employées "en arrière-plan" par de nombreux produits, est de les convertir en une valeur décimale où la "date" est la partie entière de la valeur décimale et le "temps" est la fraction valeur. Ainsi, 1900-01-01 00:00:00 est stocké en tant que 0.0 et le 20 septembre 2016 9:34:00 est stocké en tant que 42631.39861. 42631 est le nombre de jours depuis le 1900-01-01. .39861 est la partie du temps écoulé depuis minuit. N'utilisez pas de type décimal directement pour ce faire, utilisez un type de date / heure explicite; mon point ici est juste une illustration.
Le stockage des données dans deux colonnes distinctes signifie que vous devrez combiner les deux valeurs de colonne chaque fois que vous voulez voir si un moment donné est antérieur ou postérieur à la valeur stockée.
Si vous stockez les valeurs séparément, vous rencontrerez invariablement des "bogues" difficiles à détecter. Prenez par exemple ce qui suit:
IF OBJECT_ID('tempdb..#DT') IS NOT NULL
DROP TABLE #DT;
CREATE TABLE #DT
(
dt_value DATETIME NOT NULL
, d_value DATE NOT NULL
, t_value TIME(0) NOT NULL
);
DECLARE @d DATETIME = '2016-09-20 09:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
SET @d = '2016-09-20 11:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.dt_value >= '2016-07-01 11:00:00';
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.d_value >= CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00');
Dans le code ci-dessus, nous créons une table de test, la remplissons avec deux valeurs, puis effectuons une requête simple sur ces données. La première SELECT
renvoie les deux lignes, mais la seconde SELECT
ne renvoie qu'une seule ligne, ce qui peut ne pas être le résultat souhaité:
La bonne façon de filtrer une plage de date / heure où les valeurs sont dans des colonnes discrètes, comme indiqué par @ypercube dans les commentaires, est:
WHERE dt.d_value > CONVERT(DATE, '2016-07-01') /* note there is no time component here */
OR (
dt.d_value = CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00')
)
Si vous avez besoin de séparer la composante temporelle à des fins d' analyse , vous pouvez envisager d'ajouter une colonne calculée et persistante pour la partie temporelle de la valeur:
ALTER TABLE #DT
ADD dt_value_time AS CONVERT(TIME(0), dt_value) PERSISTED;
SELECT *
FROM #dt;
La colonne persistante pourrait alors être indexée, ce qui permettrait des tri rapides, etc., par heure de la journée.
Si vous envisagez de diviser la date et l'heure en deux champs à des fins d'affichage, vous devez vous rendre compte que le formatage doit être effectué sur le client, pas sur le serveur.