Pregunta

Tengo una tabla como la siguiente

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

Se supone que debo encontrar todas las tarifas que son efectivas para la fecha actual y posteriores. Entonces, para obtener la tasa efectiva actual, uso

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

para las tarifas después de la fecha actual de la consulta

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

Para combinar estos dos resultados, uso una unión como

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'

El resultado esperado es

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

Pero obtengo el resultado real como

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

No tengo ni idea de por qué sucede esto. ¿Alguna sugerencia?

¿Fue útil?

Solución

Funciona de esta manera:

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'

Otros consejos

Se ignora Order By en una instrucción select que forma parte de una unión. Por lo tanto, su TOP 1 está seleccionando algún registro arbitrario (probablemente el primer registro de la clave agrupada para la tabla).

Ordenar por no es válido cuando se usa con una Unión ...

Trabajé de manera rápida y sucia usando la expresión de tabla común con algunos trucos de declaración de rango y caso para obtener los resultados que estabas buscando ...

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

Para explicar lo que está sucediendo ...

El CTE define la velocidad, la fecha, los indicadores actuales y de clasificación devueltos por la consulta ...

El CASO separa los resultados en aquellos que son anteriores a la fecha de búsqueda y aquellos que son posteriores a la fecha de búsqueda. Utilizamos los resultados del caso (Cur) en nuestra unión para extraer los resultados de la lista particionada. .

La función Rank () luego ordena la lista creando una partición en el mismo criterio que la declaración CASE usa para separar la lista ... luego ordenamos por fecha efectiva de manera descendente. Esto tomará el & Quot; pasado & Quot; enumerar y hacer que sea más actual " pasado " rango de entrada 1 ..

Luego, en la parte de unión de la consulta ...

En la parte superior, obtenemos el rango y la fecha de " past " list (cur = 0) y la primera entrada en " past " list .. (sort = 1) .. que devolverá 1 registro (o 0 si no hay registros anteriores a la fecha de búsqueda) ..

Luego lo unimos con todo el registro de " current " lista (cur = 1)

Luego, finalmente ... tomamos los RESULTADOS de UNION ... y lo ordenamos para la fecha de vigencia, dándonos todos los registros actuales, y el " más actual " registro anterior.

Creo que las consultas anteriores excluyen 01/05/2009 al usar < y > en lugar de < = y > =.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top