web-dev-qa-db-fra.com

Rechercher la date la plus proche dans SQL Server

J'ai une table dbo.X avec DateTimecolumn Y qui peut contenir des centaines d'enregistrements.

Ma procédure stockée a le paramètre @CurrentDate, Je veux connaître la date dans le column Y dans le tableau ci-dessus dbo.X qui est inférieur et le plus proche de @CurrentDate.

Comment le trouver?

28
MaxRecursion

La clause where fera correspondre toutes les lignes avec une date inférieure à @CurrentDate et, comme elles sont classées par ordre décroissant, le TOP 1 sera la date la plus proche de la date actuelle.

SELECT TOP 1 *
FROM x
WHERE x.date < @CurrentDate
ORDER BY x.date DESC
64
ederbf

Utilisez DateDiff et triez votre résultat en fonction du nombre de jours ou de secondes entre cette date et ce que l'entrée a été.

Quelque chose comme ça

    select top 1 rowId, dateCol, datediff(second, @CurrentDate, dateCol) as SecondsBetweenDates
    from myTable
    where dateCol < @currentDate
    order by datediff(second, @CurrentDate, dateCol)
13
Mikey Mouse

J'ai une meilleure solution à ce problème, je pense.

Je vais montrer quelques images pour soutenir et expliquer la solution finale.

Contexte Dans ma solution, j'ai un tableau des taux de change. Ils représentent les taux du marché pour différentes devises. Cependant, notre fournisseur de services a eu un problème avec le flux de taux et, à ce titre, certains taux ont une valeur nulle. Je veux remplir les données manquantes avec des taux pour la même devise qui sont les plus proches dans le temps du taux manquant. Fondamentalement, je veux obtenir le RateId pour le taux non nul le plus proche que je remplacerai ensuite. (Ceci n'est pas montré ici dans mon exemple.)

1) Donc, pour commencer, identifions les informations de taux manquantes:

Requête montrant mes taux manquants, c'est-à-dire ayant une valeur de taux de zéro

2) Ensuite, identifions les taux qui ne manquent pas. Requête montrant les taux qui ne manquent pas

3) Cette requête est l'endroit où la magie opère. J'ai fait une hypothèse ici qui peut être supprimée mais a été ajoutée pour améliorer l'efficacité/les performances de la requête. L'hypothèse à la ligne 26 est que je m'attends à trouver une transaction de remplacement le même jour que celle de la transaction manquante/nulle. La magie opère est la ligne 23: la fonction Row_Number ajoute un numéro automatique commençant à 1 pour l'écart de temps le plus court entre la transaction manquante et non manquante. La prochaine transaction la plus proche a un rownum de 2, etc.

Veuillez noter qu'à la ligne 25, je dois joindre les devises afin de ne pas faire de différence entre les types de devises. C'est-à-dire que je ne veux pas remplacer une devise AUD par des valeurs CHF. Je veux les devises correspondantes les plus proches.

Combinaison des deux ensembles de données avec un numéro de ligne pour identifier la transaction la plus proche

4) Enfin, permet d'obtenir des données où le RowNum est 1 La requête finale

La requête requête complète est la suivante;

    ; with cte_zero_rates as
(
        Select      * 
        from        fxrates
        where       (spot_exp = 0 or spot_exp = 0) 
),
cte_non_zero_rates as
(
        Select      * 
        from        fxrates
        where       (spot_exp > 0 and spot_exp > 0) 
)
,cte_Nearest_Transaction as
(
        select       z.FXRatesID    as Zero_FXRatesID
                    ,z.importDate   as Zero_importDate
                    ,z.currency     as Zero_Currency
                    ,nz.currency    as NonZero_Currency
                    ,nz.FXRatesID   as NonZero_FXRatesID
                    ,nz.spot_imp
                    ,nz.importDate  as NonZero_importDate
                    ,DATEDIFF(ss, z.importDate, nz.importDate) as TimeDifferece
                    ,ROW_NUMBER() Over(partition by z.FXRatesID order by abs(DATEDIFF(ss, z.importDate, nz.importDate)) asc) as RowNum
        from        cte_zero_rates z 
        left join   cte_non_zero_rates nz on nz.currency = z.currency
                    and cast(nz.importDate as date) = cast(z.importDate as date)
        --order by  z.currency desc, z.importDate desc
)
select           n.Zero_FXRatesID
                ,n.Zero_Currency
                ,n.Zero_importDate
                ,n.NonZero_importDate
                ,DATEDIFF(s, n.NonZero_importDate,n.Zero_importDate) as Delay_In_Seconds
                ,n.NonZero_Currency
                ,n.NonZero_FXRatesID
 from           cte_Nearest_Transaction n
 where          n.RowNum = 1
                and n.NonZero_FXRatesID is not null
 order by       n.Zero_Currency, n.NonZero_importDate
0
Craig Gers