如何从两个查询的并集中选择前n个,其中生成的顺序需要按个别查询排序?

Jed*_*dja 13 sql t-sql sql-server-2008 sql-server-2008-r2

假设我有一个用户名表:

Id  |  Name
-----------
1   |  Bobby
20  |  Bob
90  |  Bob
100 |  Joe-Bob
630 |  Bobberino
820 |  Bob Junior
Run Code Online (Sandbox Code Playgroud)

我想n在'Bob'的名称上返回一个匹配列表,其中结果集首先包含完全匹配,然后是类似的匹配.

我觉得这样的事情可能有用

SELECT TOP 4 a.* FROM
(
    SELECT * from Usernames WHERE Name = 'Bob'
    UNION
    SELECT * from Usernames WHERE Name LIKE '%Bob%'
) AS a
Run Code Online (Sandbox Code Playgroud)

但有两个问题:

  1. 这是一个效率低下的查询,因为子选择可以返回许多行(查看执行计划显示在顶部之前发生的连接)
  2. (几乎)更重要的是,完全匹配不会首先出现在结果中,因为结果集似乎是按主键排序的.

我正在寻找一个将返回的查询(对于TOP 4)

Id | Name
---------
20 | Bob
90 | Bob

(and then 2 results from the LIKE query, e.g. 1 Bobby and 100 Joe-Bob)
Run Code Online (Sandbox Code Playgroud)

这可能在一个查询中吗?

And*_*mar 16

您可以使用a case将完全匹配放在最上面:

select  top 4 *
from    Usernames
where   Name like '%Bob%'
order by
        case when Name = 'Bob' then 1 else 2 end
Run Code Online (Sandbox Code Playgroud)

或者,如果您担心性能并且有索引(Name):

select  top 4 *
from    (
        select  1 as SortOrder
        ,       *
        from    Usernames
        where   Name = 'Bob'
        union all
        select  2
        ,       *
        from    Usernames
        where   Name like  '%Bob%'
                and Name <> 'Bob'
                and 4 >
                (
                select  count(*)
                from    Usernames
                where   Name = 'Bob'
                )
        ) as SubqueryAlias
order by
        SortOrder
Run Code Online (Sandbox Code Playgroud)