web-dev-qa-db-fra.com

Drop Time dans DateTime

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.

17
Oliver S

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

24
SQLMenace

Vous pouvez utiliser cette syntaxe: -

CAST(date_field AS DATE) as column_name

7
Kunal Kabra

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                          
6
StingyJack

Si vous utilisez MS SQL Server 2008, vous pouvez également utiliser le nouveau type de données DATE au lieu d’utiliser DATETIME.

4
John Milazzo

Voici un moyen:

declare @d datetime
set @d = getdate()

select dateadd(d, datediff(day, 0, @d), 0)
3
AlexCuse

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
2
Emtucifor

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?

1
K. Brian Kelley

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.

1
Thorsten

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);
    }
};
1
MAgnus

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
0
feihtthief

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

0
Adam

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] ...

0
MatBailie

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.

0
Chains

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.

0
Tom H

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 ...

0
Mark Brittingham