Question

J'ai un tableau comme ci-dessous

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

Je suis censé trouver tous les tarifs en vigueur à la date du jour et après celle-ci. Donc, pour obtenir le taux effectif actuel, j'utilise

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

pour les tarifs postérieurs à la date actuelle de la requête

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

Pour combiner ces deux résultats, j'utilise une union comme

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'

Le résultat attendu est

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

Mais je reçois le résultat réel comme

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

Je ne sais pas pourquoi cela se produit? Des suggestions?

Était-ce utile?

La solution

Cela fonctionne comme suit:

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'

Autres conseils

La commande par dans une instruction select faisant partie d'une union est ignorée. Par conséquent, votre TOP 1 sélectionne un enregistrement arbitraire (probablement le premier enregistrement par la clé en cluster de la table).

Order By n'est pas valide lorsqu'il est utilisé avec une union ...

J'ai mis au point un concept rapide et coquin en utilisant Common Table Expression avec quelques astuces sur les déclarations de rang et de cas pour obtenir les résultats que vous recherchiez.

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

Pour expliquer ce qui se passe ...

Le CTE définit les indicateurs de taux, de date, de courant et de tri renvoyés par la requête ...

Le CASE sépare les résultats en ceux antérieurs à la date de recherche et en ceux postérieurs à la date de recherche. Nous utilisons les résultats du cas (Cur) dans notre syndicat pour extraire les résultats de la liste partitionnée. .

La fonction Rank () trie ensuite la liste en créant une partition sur les mêmes critères que ceux utilisés par l'instruction CASE pour séparer la liste. Nous classons ensuite par date d'effet de manière décroissante. Cela prendra le & Quot; passé & Quot; lister et mettre à jour " past " classement au rang 1 ..

Ensuite, dans la partie union de la requête.

Dans la partie supérieure, nous obtenons le rang et la date du & "passé &"; list (cur = 0) et la première entrée du & "passé &"; list .. (sort = 1) .. qui retournera 1 enregistrement (ou 0 s'il n'y a pas d'enregistrements antérieurs à la date de la recherche) ..

Ensuite, nous unissons cela à tous les enregistrements du " actuel " liste (cur = 1)

Ensuite, enfin… nous prenons les RÉSULTATS de l’UNION .. et les ordonnons d’ici à la date d’entrée en vigueur, nous donnant ainsi tous les enregistrements en cours, ainsi que le & «plus récent &»; enregistrement précédent.

Je crois que les requêtes ci-dessus excluent le 01/05/2009 en utilisant < et > au lieu de < = et > = =.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top