SQL:在使用Order By的UNION查询中使用Top 1

Raj*_*S P 18 sql-server union sql-order-by

我有一张桌子如下

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
Run Code Online (Sandbox Code Playgroud)

我应该找到对当前日期和之后有效的所有费率.因此,为了获得当前有效率,我使用

SELECT TOP 1 * from table 
where effective_date < '05/05/2009' 
order by effective date desc
Run Code Online (Sandbox Code Playgroud)

查询当前日期之后的费率

SELECT * from table 
where effective_date > '05/05/2009'
Run Code Online (Sandbox Code Playgroud)

要结合这两个结果,我使用union作为

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'
Run Code Online (Sandbox Code Playgroud)

预期的结果是

Rate Effective Date
---- --------------
5.8  05/01/2009
5.4  06/01/2009
5.8  12/01/2009
6.0  03/15/2009
Run Code Online (Sandbox Code Playgroud)

但我得到了实际的结果

Rate Effective Date
---- --------------
5.6  02/02/2009
5.4  06/01/2009
5.8  12/01/2009
6.0  03/15/2009
Run Code Online (Sandbox Code Playgroud)

我不清楚为什么会这样?有什么建议?

spl*_*tne 27

它以这种方式工作:

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'
Run Code Online (Sandbox Code Playgroud)


Ant*_*nes 8

将忽略作为联合一部分的select语句中的Order By.因此,您的TOP 1正在选择一些仲裁记录(可能是该表的聚簇键的第一条记录).


dat*_*cop 5

与 Union 一起使用时,Order By 无效...

我使用 Common Table Expression 和一些 Rank 和 Case 语句技巧处理了一个快速而肮脏的事情,以获得您正在寻找的结果。

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
Run Code Online (Sandbox Code Playgroud)

为了解释正在发生的事情......

CTE 定义了从查询返回的速率、日期、当前和排序标志...

CASE 将结果分为搜索日期之前的结果和搜索日期之后的结果。我们使用联合中案例 (Cur) 的结果从分区列表中提取结果。

Rank() 函数然后通过根据 CASE 语句用于分隔列表的相同条件创建一个分区来对列表进行排序..然后我们以降序方式按生效日期排序。这将采用“过去”列表并使其成为最新的“过去”条目排名 1..

然后在查询的联合部分..

在顶部,我们从“过去”列表(cur = 0)和“过去”列表中的第一个条目..(排序 = 1)中获取排名和日期,这将返回 1 条记录(或如果在搜索日期之前没有记录,则为 0)。

然后我们将它与“当前”列表中的所有记录合并(cur = 1)

然后最后.. 我们取 UNION 的 RESULTS .. 并在生效日期之前对它进行排序,为我们提供所有当前记录,以及“最新”的先前记录。