2

Suppose I have this data:

create table People (ID int identity, Name nvarchar(50), Age int);   
insert into People values 
  ('Bill Jones', 50),
  ('Bill Jones', 12),
  ('Sam Smith', 23),
  ('Jill Brown', 44),
  ('Jill Brown', 67),
  ('Jill Brown', 3)

And this query:

select * from (
   select 
       ID, Name, Age, 
       row_number() over (partition by Name order by ID) [rownum]
   from People
) a where [rownum] = 1

It successfully returns me one person per unique name.

ID  NAME        AGE ROWNUM
1   Bill Jones  50  1
4   Jill Brown  44  1
3   Sam Smith   23  1

However, in order to use row_number(), I must specify an order by, causing the query plan to include an expensive sort operation.

query plan

I don't care about which person is returned; I just need one person per name.

Is there a way to do this without the sorting?

You can see my query and execution plan here: http://sqlfiddle.com/#!3/3ee32/1/0

4

4 回答 4

2

我不知道它是否选择了一个,但它显示了你想要的记录......没有按子句排序/.....

Select * from People a where id in (Select Top(1) id from people b where name in
                                  (Select name from people group by name) and a.name=b.name)

Sql Fiddler 演示链接

于 2013-05-01T05:09:48.743 回答
1

您可能会考虑以下查询:

SELECT 
  a.* 
FROM 
  People a 
LEFT JOIN 
  People b 
ON
  (a.Name = b.Name AND a.id > b.id) 
WHERE b.id IS NULL

当我在 SQLFiddle 中运行它时,它似乎表现更好:

原始查询:0.0146747

自加入: 0.0071784

于 2013-05-01T05:21:49.803 回答
1

查询如何:

select 
    distinct Name, 
    (Select top 1 Age from People b where b.Name=a.Name) Age 
from People a

或者

select b.* From(
    select min(ID) ID from people group by Name
    ) a inner join People b on a.ID=b.ID

与所有列。 事实:这些查询中没有一个能胜过使用 ROW_NUMBER() 的查询!

于 2013-05-01T05:03:40.877 回答
1

我实际上看到了编写原始查询的不同方法。您也可以考虑使用Common Table Expression. 虽然我相信优化水平几乎是一样的。我确实更喜欢CTE

with cte
as
(
    select ID, Name, Age, 
           row_number() over (partition by Name order by ID) [rownum]
    from People
)

select * 
from cte 
where [rownum] = 1
于 2013-05-01T05:57:52.630 回答