2012-12-24 18 views
18

Ho una tabella dbo.X con DateTimecolumn Y che può avere centinaia di record.Trova la data più vicina in SQL Server

mio stored procedure ha parametro @CurrentDate, voglio scoprire la data nella column Y nella tabella dbo.X di sopra del quale è inferiore e più vicina alla @CurrentDate.

Come trovarlo?

risposta

48

La clausola where corrisponderà tutte le righe con data meno di @CurrentDate e, dal momento che sono ordinati in modo discendente, il TOP 1 sarà la data più vicina alla data corrente.

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

Ma quanto è efficiente? – MaxRecursion

+1

Dipende dal design del database. Suggerisco di provare a impostare un indice sulla tabella per il campo della data, in modo che il sistema possa andare direttamente al valore corrispondente alla query. – ederbf

+0

grazie mille per l'aiuto. – MaxRecursion

7

Usa DateDiff e ordinare il risultato per quanti giorni o secondi sono tra tale data e ciò che la voce è stata

Qualcosa di simile

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

In ORDER BY, è possibile fare riferimento alle colonne in base al loro alias (ad esempio, è possibile "ORDER BY SecondsBetweenDate'). Tuttavia, stai ordinando le righe in base a un'espressione anziché a una colonna. È probabile che la query non sia [sargable] (http://en.wikipedia.org/wiki/Sargable "Sargable (Wikipedia)"). Solo una nota. –

+0

@AndriyM Ah, non lo sapevo, grazie per il suggerimento –

-7
CREATE PROCEDURE CurrentDate 
@CurrentDate DATETIME 
AS 
BEGIN 
    Select * from orders 
    where OrderDate < @CurrentDate 
END 
GO 
-1

ho una soluzione migliore per questo problema credo.

Mostrerò alcune immagini per supportare e spiegare la soluzione finale.

Sfondo Nella mia soluzione ho una tabella di tassi FX. Questi rappresentano i tassi di mercato per diverse valute. Tuttavia, il nostro fornitore di servizi ha avuto un problema con il feed rate e in quanto tali alcune tariffe hanno valori zero. Voglio riempire i dati mancanti con i tassi per quella stessa valuta che sono i più vicini nel tempo al tasso mancante. Fondamentalmente voglio ottenere il RateId per la tariffa non zero più vicina che sostituirò. (Questo non è mostrato qui nel mio esempio.)

1) Quindi, per iniziare consente di identificare il tassi di informazioni mancanti:

Query showing my missing rates i.e. have a rate value of zero

2) successiva consente di individuare tariffe mancano . Query showing rates that are not missing

3) Questa query è dove avviene la magia. Qui ho fatto un'ipotesi che può essere rimossa, ma è stata aggiunta per migliorare l'efficienza/le prestazioni della query. L'assunto sulla linea 26 è che mi aspetto di trovare una transazione sostitutiva lo stesso giorno della transazione mancante/zero. La magia accade è la riga 23: La funzione Numero_riga aggiunge un numero automatico che inizia a 1 per la differenza di tempo più breve tra la transazione mancante e quella mancante. La transazione successiva più vicina ha un rownum di 2 ecc.

Si prega di notare che nella riga 25 devo unire le valute in modo che non mismatch i tipi di valuta. Questo è che non voglio sostituire una valuta AUD con valori in CHF. Voglio le valute di corrispondenza più vicine.

Combining the two data sets with a row_number to identify nearest transaction

4) Infine, consente di ottenere dati in cui il rownum è 1 The final query

La query full interrogazione è la seguente;

; 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 
Problemi correlati