J'ai un problème où ma table enregistre la date
2009-01-10 10:00:00.000
et j'ai une autre table qui stocke la date
2009-01-10 12:00:00.000
Je sais qu'ils ne sont pas identiques, mais que les dates le sont. Y a-t-il moyen de supprimer facilement l'heure avec SQL et de ne conserver que les dates aux fins de comparaison? Merci.
Lance ça
SELECT DATEADD(dd, DATEDIFF(d, 0, Getdate()), 0)
remplacez Getdate () par le nom de votre colonne pour effacer la date
BTW si vous faites une comparaison, il est préférable de faire> = et <car cela donnera de meilleurs résultats
Vous pouvez utiliser cette syntaxe: -
CAST(date_field AS DATE) as column_name
Regardez ici
Tu veux le premier.
SELECT (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime))
N'utilisez pas de conversions à varchar, elles sont lentes.
EDIT: @feihtthief - Voici un moyen de renseigner une table de dates (avec 0 heure) à partir d'une table de nombres temporaires FAST. Modifiez-le pour sauvegarder le tableau de nombres si vous le souhaitez. Ils sont pratiques aussi.
DECLARE @DaysFromGoLive int
SET @DaysFromGoLive = (SELECT (DATEDIFF(dd,'10/01/2007',GETDATE()) + 1)) /* Days from go live is the starting date of the table */
SELECT TOP 10950 --30 years of days
IDENTITY(INT,1,1) as N
INTO #Numbers
FROM Master.dbo.SysColumns sc1,
Master.dbo.SysColumns sc2
CREATE TABLE [dbo].[TableOfDates](
[fld_date] [datetime] NOT NULL,
CONSTRAINT [PK_TableOfDates] PRIMARY KEY CLUSTERED
(
[fld_date] ASC
)WITH FILLFACTOR = 99 ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO
dbo.TableOfDates
SELECT
DATEADD(dd,nums.n - @DaysFromGoLive,CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)) as FLD_Date
FROM #Numbers nums
SELECT MIN(FLD_Date) FROM dbo.TableOfDates
SELECT MAX(FLD_Date) FROM dbo.TableOfDates
DROP TABLE #Numbers
Si vous utilisez MS SQL Server 2008, vous pouvez également utiliser le nouveau type de données DATE au lieu d’utiliser DATETIME.
Voici un moyen:
declare @d datetime
set @d = getdate()
select dateadd(d, datediff(day, 0, @d), 0)
La conversion en varchar est lente. Ne le fais pas. La solution Datediff est la plus rapide. Si vous comparez avec une date, vous n’avez même pas besoin d’utiliser dateadd (ou de convertir en datetime) car l’entier sera comparé implicitement à une date sans problème, comme dans:
WHERE SomeDate = DateDiff(d, 0, GetDate())
La suggestion de Mark Brittingham concernant une jointure entre deux tables est plutôt bonne. Et pour comparer à une seule date, comme suggéré, utilisez:
WHERE A.Dt >= @SomeDate AND A.Dt < @SomeDate + 1
Toutes ces solutions (à l'exception de la publication de type de données SQL Server 2008) sont des solutions basées sur des lignes. Ils fonctionneront bien dans les petites tables, mais dans de très grandes tables. Si vous n'êtes pas sur 2008, avez-vous la possibilité de stocker la date sous forme de champs de nombre entier distincts pour l'année, le mois et le jour ou sous forme de calcul à partir d'une date fixe?
Dans Oracle, vous pouvez faire un tronc (DateTime) qui supprime le composant time. (Il existe des variantes telles que trunc (DateTime, 'MONTH') qui donne la première date du mois.) Je ne sais pas s'il s'agit de SQL standard, mais je suis sûr que des fonctions similaires existeraient dans d'autres bases de données.
Cela devrait être beaucoup plus rapide que de travailler avec une fonction de conversion.
Une fonction SQL CLR comme celle-ci devrait:
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlDateTime StripTime(SqlDateTime date)
{
return date.IsNull ? SqlDateTime.Null : new SqlDateTime(date.DayTicks, 0);
}
};
StingyJack a raison, mais selon ce que vous voulez faire, vous pourriez être le meilleur serveur pour stocker la date sous forme d'entier si vous n'avez jamais besoin de la partie heure.
create table #datedemo(
id integer primary key identity(1,1) not null
,date datetime not null
,dateint int
)
insert into #datedemo (date)
select '2009-Jan-29 02:12:00'
union all select '2009-Jan-29 16:22:00'
union all select '2009-Jan-30 00:32:00'
union all select '2009-Jan-30 13:42:00'
union all select '2009-Jan-31 01:52:00'
union all select '2009-Feb-01 12:02:00'
update #datedemo set dateint = floor(cast(date as float))
select id,date,dateint,cast(dateint as datetime) from #datedemo
where dateint = floor(cast(cast('2009-Jan-30' as datetime)as float))
drop table #datedemo
Ma méthode préférée pour afficher (et comparer) uniquement la date consiste à utiliser:
convert(char(10),getdate(),101)
où getdate () peut être votre valeur datetime.
je crois qu'il convertit au format MM/JJ/AAAA
La suggestion de SQLMenaces est, à mon avis, le moyen le plus rapide de supprimer les délais d'une date. Cependant, certaines requêtes deviennent comme un cochon en supprimant la possibilité d'utiliser des index ...
[A] JOIN [B] ON SQLMenace([A].datetime) = SQLMenace([B].datetime)
(Where SQLMenace() is the operation he described *grin*)
Pour utiliser autoriser l'utilisation des index sur la 2ème table, il suffit d'une petite adaptation ...
[A] JOIN [B] ON [A].datetime >= SQLMenace([B].datetime) AND [A].datetime < SQLMenace([B].datetime)
Cela devrait entraîner une analyse sur [B] et des recherches d'index sur [A] ...
Selon la raison pour laquelle vous mettez à zéro le temps ...
Pour moi, c’est souvent pour que je puisse comparer deux dates . Dans ce cas, vous feriez mieux de vous en tenir aux comparaisons> =, <= (éviter =, <>) si vous le pouvez. De cette manière, vous pouvez faire les comparaisons dans votre clause WHERE sans perdre le bénéfice de votre index.
Si vous utilisez SQl-Server 2008, ils ont maintenant un type de données DATE (qui n'inclut pas l'heure)
Vous pouvez utiliser certains formats de stockage de créations, par exemple une petite taille (deux fois plus petite que la taille d'une petite taille) de YYDDD, où DDD est la date julienne (chaque jour de l'année est numéroté de 1 à 365). Ce type de données est plus petit et valide pour les comparaisons>, =, <. L'inconvénient est de devoir convertir les dates externes en ce format (ou inversement) avant de faire une comparaison.
Je suppose qu'une dernière chose à considérer est d'empêcher que les données temporelles soient stockées en premier lieu.
Vous pouvez également faire YEAR()
, MONTY()
, etc., qui renverra des valeurs entières. Peut-être pas le mieux pour comparer les dates, mais utile pour le formatage, etc.
Ma suggestion est de choisir une norme et de modifier l'une des tables pour qu'elle corresponde à l'autre. Sinon, votre code d'application devra se rappeler quelle table utilise quelle méthode pour toujours. Choisissez une norme et respectez-la. S'il est vraiment toujours minuit dans une table et toujours midi dans l'autre table, la partie heure de la date n'a de toute façon aucune signification.
Il existe de nombreuses suggestions pour prendre le temps mais si vous cherchez simplement un moyen de comparer les jours sans prendre en compte la composante temps, procédez comme suit:
Select * From SomeTable Where (DateDiff(d, FirstDate, SecondDate) = 0)
Autrement dit, utilisez DateDiff avec un argument "d" pour effectuer votre comparaison plutôt que "=".
Juste au cas où c'est ce que vous êtes vraiment après ...