2009-10-05 16 views
6

Utilizzo di SQL Server 2008. Ho un proc memorizzato che ha data di inizio e fine come parametri di input per l'intervallo di date.Una query sql singola in grado di gestire sia l'intervallo di date nullo che il valore in sql server

Ricerca di una query singola sql con una data tra inizio e fine nella clausola where che può gestire entrambi i casi in cui le date sono sia nulle che entrambe hanno valori.

Non voglio utilizzare un'istruzione IF.

+0

La prego di inviare quale sarebbe la vostra richiesta simile da entrambi i parametri definiti? – Quassnoi

risposta

12
WITH limits AS 
     (
     SELECT COALESCE(@startDate, MIN(mydate)) AS startDate, COALESCE(@endDate, MAX(mydate)) AS endDate 
     FROM mytable 
     ) 
SELECT m.* 
FROM limits 
JOIN mytable m 
ON  mydate BETWEEN startDate AND endDate 

Ciò sarà più efficace se v'è un indice sulla mydate, poiché questa condizione è sargable e userà una Index Seek.

Se non c'è indice, utilizzare i costrutti IFNULL proposti da altri.

+1

Bello. Mi piace limitare l'intervallo di date a ciò che è già presente nella tabella. – dnagirl

+0

Fai attenzione: le chiamate min/max() sono costose in assenza di indice di data buona (che l'utente non ha specificato esplicitamente) – DVK

+0

Per quanto io odio votare contro me stesso, questo sembra essere il migliore, supponendo che esista un indice . +1 – wcm

9

È possibile farlo:

SELECT blah 
FROM MyTable 
WHERE 
    (@startDate IS NULL OR MyTable.StartDate >= @startDate) 
    AND (@endDate IS NULL OR MyTable.EndDate <= @endDate) 

Ma si prega di essere consapevole del fatto che un gran numero di parametri e clausole di questo tipo può portare a piani di query in modo non corretto nella cache. Ci sono molte domande su SO su piani di query errati e parametri 'sniffing'.

4

risposta di Quassnoi è probabilmente meglio, ma ecco un altro introito:

SELECT * 
FROM MyTable 
WHERE 
    MyTable.StartDate >= ISNULL(@startDate, MyTable.StartDate) 
    AND MyTable.EndDate <= ISNULL(@startDate, MyTable.EndDate) 
+1

Attenzione questo impedisce l'uso dell'indice. – recursive

+0

Penso che questo sia leggermente più facile da leggere ma penso che il ricorsivo sia corretto. – wcm

+0

+1: utile ma ricorsivo è un buon punto per quanto riguarda l'indice. –

2
SELECT * 
FROM MyTable 
WHERE 
    MyTable.StartDate >= COALESCE(MyTable.StartDate, "1/1/1900") 
    /* Date selected as earliest plausible constant to avoid min() lookup */ 

AND MyTable.EndDate <= COALESCE(MyTable.EndDate, "1/1/3001") 
    /* Date selected as latest plausible constant to avoid max() lookup */ 

È necessario selezionare le costanti corretti per il proprio app/dominio, ovviamente. È un po 'rischioso se non si dispone di costanti sufficientemente grandi ma molto più veloci di quelle esplicitamente min/max up dalla tabella, e la maggior parte delle app/domini hanno cornici ben definite.

1
SELECT 
    Column1,.... 
    FROM MyTable 
    WHERE MyTable.StartDate>=COALESCE(@startDate,CONVERT(datetime,'01/01/1753')) 
     AND MyTable.EndDate<=COALESCE(@endDate,CONVERT(datetime,'12/31/9999')) 

anche, ecco un articolo molto esauriente su questo argomento:

Dynamic Search Conditions in T-SQL by Erland Sommarskog

che copre tutte le questioni e le modalità di cercare di scrivere query con più condizioni di ricerca opzionali

qui è il sommario:

Introduction 
     The Case Study: Searching Orders 
     The Northgale Database 
    Dynamic SQL 
     Introduction 
     Using sp_executesql 
     Using the CLR 
     Using EXEC() 
     When Caching Is Not Really What You Want 
    Static SQL 
     Introduction 
     x = @x OR @x IS NULL 
     Using IF statements 
     Umachandar's Bag of Tricks 
     Using Temp Tables 
     x = @x AND @x IS NOT NULL 
     Handling Complex Conditions 
    Hybrid Solutions – Using both Static and Dynamic SQL 
     Using Views 
     Using Inline Table Functions 
    Conclusion 
    Feedback and Acknowledgements 
    Revision History 
0

Per il valore massimo:

Case when @a > @b or @b is null then @a else @b end. 

Questo gestisce anche i valori nulli.

Semplice.

1

È possibile farlo

SELECT blah 
FROM MyTable 
WHERE 
1 = case 
     when @startDate IS NOT NULL then MyTable.Date >= @startDate 
    else 1 end 
AND 
1 = case 
     when @endDate IS NOT NULL then MyTable.Date <= @endDate 
    else 1 end 

o

SELECT blah 
FROM MyTable 
WHERE 
(
    (@startDate is not null and @endDate is not null and MyTable.Date between @startDate and @endDate) 
    or 
    (@startDate is null and @endDate is null) 
) 
Problemi correlati