Shawn

智慧本身就是好的。有一天我们都会死去,追求智慧的道路还会有人在走着。死掉以后的事我看不到,但在我活着的时候,想到这件事,心里就很高兴。 —— 王小波

导航

SQL 分组后取最小行号记录

本示例测试两个表联接查询后,分组并取分组后的最小行号记录

测试表:

tb1表结构如下:

CREATE TABLE [dbo].[tb1](
    [a] [nvarchar](50) NOT NULL,
    [b] [nvarchar](50) NULL,
    [c] [nvarchar](50) NULL,
 CONSTRAINT [PK_tb1] PRIMARY KEY CLUSTERED 
(
    [a] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

tb2表结构如下:

CREATE TABLE [dbo].[tb2](
    [cc] [nvarchar](50) NOT NULL,
    [dd] [nvarchar](50) NULL,
    [bb] [nvarchar](50) NULL,
 CONSTRAINT [PK_tb2] PRIMARY KEY CLUSTERED 
(
    [cc] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

tb1表内容:

a    b     c

1    2    adf
2    2    dfd
3    3    测试3
4    3    测试4

tb2表内容:

cc   dd         bb

1    中国菜      2
2    印度菜      2
3    西餐         3
4    日本料理    3

两个表相关联字段tb1.b=tb2.bb

有两种方法使用SQL可实现:

第一种方法如下:

select *  from
(select tb1.b,tb1.c,tb2.dd,ROW_NUMBER() over(order by tb1.b) as rowID from tb1 
left join tb2 on tb1.b=tb2.bb group by tb1.b,tb1.c,tb2.dd )d  --查询行号
where d.rowID in 
(select minrowID from (               --找最小行号集合
select b,MIN(rowID) as minrowID from  --取每个组的最小行号
(select tb1.b,tb1.c,tb2.dd,ROW_NUMBER() over(order by tb1.b) as rowID from tb1 
left join tb2 on tb1.b=tb2.bb group by tb1.b,tb1.c,tb2.dd     --查询行号
)a  group by a.b)c)

执行结果分析信息如下:

image

第二种方法如下:

select *
from (select tb1.b,tb1.c,tb2.dd,ROW_NUMBER() over(order by tb1.b) as rowID from tb1 
left join tb2 on tb1.b=tb2.bb group by tb1.b,tb1.c,tb2.dd) t
where not exists (select 1 from 
(select tb1.b,tb1.c,tb2.dd,ROW_NUMBER() over(order by tb1.b) as rowID from tb1 
left join tb2 on tb1.b=tb2.bb group by tb1.b,tb1.c,tb2.dd)a where b=t.b and rowID< t.rowID)

执行分析结果如下:

image

 

通过两种方式对比,可发现第二种方案执行效率较高,如还有更好的方案,欢迎指教!

执行结果:

image

posted on 2013-09-27 13:41  ShawnZhou  阅读(1069)  评论(0编辑  收藏  举报