Domanda

Ho una tabella come di seguito

Rate Effective_Date
---- --------------
5.6  02/02/2009
5.8  05/01/2009
5.4  06/01/2009
5.8  12/01/2009
6.0  03/15/2009

Dovrei trovare tutte le tariffe in vigore per la data corrente e successivamente.Quindi, per ottenere il tasso effettivo attuale, utilizzo

SELECT TOP 1 * from table 
where effective_date < '05/05/2009' 
order by effective date desc

per le tariffe successive alla data corrente la query è

SELECT * from table 
where effective_date > '05/05/2009'

Per combinare questi due risultati utilizzo un'unione as

SELECT TOP 1 * from table 
where effective_date < '05/05/2009' 
order by effective date desc

UNION

SELECT * from table 
where effective_date > '05/05/2009'

Il risultato atteso è

Rate Effective Date
---- --------------
5.8  05/01/2009
5.4  06/01/2009
5.8  12/01/2009
6.0  03/15/2009

Ma ottengo il risultato effettivo come

Rate Effective Date
---- --------------
5.6  02/02/2009
5.4  06/01/2009
5.8  12/01/2009
6.0  03/15/2009

Non ho la più pallida idea del perché questo accada?Eventuali suggerimenti?

È stato utile?

Soluzione

Funziona in questo modo:

select *
from (
    select top 1 *
    from table
    where effective_date <= '05/05/2009'
    order by effective_date desc
) as current_rate

union all

select *
from table
where effective_date > '05/05/2009'

Altri suggerimenti

ORDER BY in un'istruzione SELECT che fa parte di un'unione viene ignorato. Quindi il vostro TOP 1 è la selezione di alcuni record di arbitrario (probabilmente il primo record dalla chiave cluster per la tabella).

Ordina per non è valido se utilizzato con un'Unione...

Ho elaborato una cosa veloce e sporca utilizzando l'espressione di tabella comune con alcuni trucchi con le istruzioni Rank e Case per ottenere i risultati che stavi cercando.

WITH CTE_RATES ( RATE, EFFECTIVE_DATE, CUR, SORT )
AS (
    SELECT 
        Rate,
        Effective_date,
        CASE WHEN Effective_date > '5/5/2009' THEN 1
             ELSE 0
        END,
        RANK() OVER (PARTITION BY
                         CASE WHEN EFFECTIVE_DATE > '5/5/2009' THEN 1
                              ELSE 0
                         END
                     ORDER BY EFFECTIVE_DATE DESC)
    FROM TestTable
)

SELECT RATE, EFFECTIVE_DATE
FROM (
    SELECT RATE, EFFECTIVE_DATE 
    FROM CTE_RATES 
    WHERE CUR = 0 AND SORT = 1

    UNION ALL

    SELECT RATE, EFFECTIVE_DATE
    FROM CTE_RATES
    WHERE CUR = 1
    ) AS QRY
ORDER BY EFFECTIVE_DATE

Per spiegare cosa sta succedendo...

Il CTE definisce la frequenza, la data, i flag correnti e di ordinamento restituiti dalla query...

Il CASE separa i risultati in quelli precedenti alla data di ricerca e quelli successivi alla data di ricerca.Utilizziamo i risultati del caso (Cur) nella nostra unione per estrarre i risultati dall'elenco partizionato.

La funzione Rank() ordina quindi l'elenco creando una partizione in base agli stessi criteri utilizzati dall'istruzione CASE per separare l'elenco.quindi ordiniamo in base alla data di entrata in vigore in modo decrescente.Questo prenderà l'elenco "passato" e renderà la sua voce "passata" più recente al livello 1..

Quindi nella parte di unione della query...

Nella parte superiore otteniamo il rango e la data dall'elenco "passato" (cur = 0) e la prima voce nell'elenco "passato".(ordinamento = 1)..ciò restituirà 1 record (o 0 se non sono presenti record precedenti alla data di ricerca).

Quindi lo uniamo a tutto il record dell'elenco "corrente" (cur = 1)

Poi finalmente..prendiamo i RISULTATI dell'UNIONE..e ordinarlo entro la data di entrata in vigore fornendoci tutti i record attuali e il record precedente "più recente".

Credo che le query di cui sopra sono esclusi 05/01/2009 utilizzando lt &; e GT &; invece di lt &; = e gt &;. =

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top