2010-09-23 3 views
4

J'ai deux champs "date" auxquels je dois participer.SQL Méthode la plus rapide pour comparer deux dates (format varchar et datetime non standard)

Le premier est un datetime normal dans le format yyyy-mm-dd hh:mm:ss

Le second est un varchar (8) dans le format de l'enfant étape à tête rouge mmddyyyy

Maintenant, cela devient pénible, car il n'y a pas moyen facile de convertir au type correspondant. Il y a un format intégré qui est yyyymmdd mais qui ne correspond pas au format varchar.

Il y a deux chemins que je vois:

declare @normal_date as datetime; 
declare @hated_date as varchar(8); 

set @normal_date='1974-11-01 00:00:00.000' 
set @hated_date='11011974' 

--cast to date time with string splits 
select @normal_date 
where CONVERT(datetime, RIGHT(@hated_date,4)+LEFT(@hated_date,2)+SUBSTRING(@hated_date,3,2))[email protected]_date 

--convert normal date to ackward format 
select @normal_date 
     where REPLACE(CONVERT(varchar(10),@normal_date,101), '/','')[email protected]_date 

Quel est le meilleur? Ou y a-t-il un meilleur moyen?

Edité pour montrer les coûts

--Operator cost (39%) 
CONVERT(datetime, RIGHT(@hated_date,4)+LEFT(@hated_date,2)+SUBSTRING(@hated_date,3,2))[email protected]_date 

--Operator cost (57%) 
REPLACE(CONVERT(varchar(10),@normal_date,101), '/','')[email protected]_date 

--Operator cost (46%) 
cast(stuff(stuff(@hated_date, 3,0, '/'),6,0,'/') as datetime)[email protected]_date 

--Operator cost (47%) 
RIGHT(@hated_date, 4) + LEFT(@hated_date, 4)[email protected]_date 
+0

Le coût de l'opérateur du plan d'exécution est dénué de sens. Vous devez exécuter chacun un million de fois en utilisant 'SET STATISTICS IO ON' et comparer. Je pense que vous trouverez que la plupart d'entre eux sont à peu près les mêmes. – ErikE

Répondre

5

Ceci est aaaammjj pas?

RIGHT(@hated_date, 4) + LEFT(@hated_date, 4) 

Ainsi, votre script devient

declare @normal_date as datetime; 
declare @hated_date as varchar(8); 

set @normal_date='1974-11-01 00:00:00.000' 
set @hated_date='11011974' 

--SELECT @hated_date = RIGHT(@hated_date, 4) + LEFT(@hated_date, 4)) 

select 'hurrah' WHERE @normal_date = RIGHT(@hated_date, 4) + LEFT(@hated_date, 4) 
+0

J'ai testé les performances de votre méthode. –

+0

@Denis Valeev: Avez-vous testé sur une table ou juste une ligne comme ci-dessus? – gbn

+1

Voir ma réponse; vous étiez censé le lire. :) –

2

Essayez ceci:

select cast(stuff(stuff('11011974', 3,0, '/'),6,0,'/') as datetime) 

Mise à jour

alt text

+0

Vous pouvez ajouter 'set dateformat mdy' avant cette requête. –

+0

qui fonctionne, mais c'est la même performance que les autres. Je dirai que le format «haï» est le format qui aura moins d'enregistrements. – Nix

+1

@Nix Comment mesurez-vous la performance de différentes méthodes? Exécuter en production? –

2

Une autre approche est la suivante:

MONTH(@normal_date)*1000000 + DAY(@normal_date)*10000 + YEAR(@normal_date) 
= 
CAST(@hated_date AS INT) 

une chose: il est plus précis pour comparer les coûts réels d'exécution que de compter sur de l'optimiseur estimations.

+0

On dirait que votre approche est la plus rapide en fonction de mes résultats. Ce qui est un peu biaisé bien sûr et cela doit être prouvé sur le serveur de production de Nix pour être le dernier mot. –

+0

Je ne dirais pas "plus précis" car les coûts du plan d'exécution sont presque insignifiants dans un cas comme celui-ci. Je dirais "le seul moyen". – ErikE

2

Vous suggérons de fixer la colonne à date/heure ou d'ajouter une colonne datetime à la table et de convertir les données afin que vous ayez à effectuer cette conversion une fois que les données sont saisies (et bien sûr pour les données existantes) pourrait même être une colonne calculée. Ce n'est pas quelque chose que vous voulez faire dans certaines instructions. Si nécessaire, créez une table dateconversion avec chaque date opossible dans les deux formats et joignez-la si la table ne peut pas être modifiée.

Vous pouvez également vérifier qu'il n'y a pas de dates non valides, ce qui est toujours possible avec des dates de stockage dans un type de données autre qu'un datetime.

+0

'Si nécessaire, créez une table dateconversion avec chaque date opossible dans les deux formats et joignez-y si la table ne peut pas être changée.» Êtes-vous sûr que ce serait plus rapide qu'une simple manipulation de chaîne? –

+0

S'il est indexé, je m'attendrais à ce qu'il soit plus rapide, mais vous devrez le tester. Cela pourrait dépendre du nombre d'enregistrements impliqués. Les conversions sont généralement lentes. Mais fixer la structure de la base de données est le meilleur choix de tous. Cela facilite les comparaisons, il est impossible de mettre des données qui ne sont pas une date et cela facilitera les autres requêtes où vous devez aussi faire des calculs de données. – HLGEM

+0

Impossible de modifier les tables. J'aimerais ... pas sûr pourquoi vous iriez avec une date "varchar" qui est dans un mauvais format. – Nix

Questions connexes