承接国内外服务器租用托管、定制开发、网站代运营、网站seo优化托管接单、网站代更新,新老站点皆可!!咨询QQ:3787320601

针对distinct疑问引发的一系列思考

管理员 2023-07-05 09:29:08 互联网圈 8 ℃ 0 评论 4744字 收藏

有人提出了这样一个问题,整理出来给大家也参考一下

假定有以下这样一张表格:

这里的数据,具有以下的特点:在一个DepartmentId中,可能会有多个Name,反之也是一样。就是说Name和DepartmentId是多对多的关系。

现在想实现这样一个查询:依照DepartmentID排完序以后(第一步),再获得Name列的不重复值(第二步),而且要保存在第一步后的相对顺序。以本例而言,应当返回三个值顺次是:ACB

我们首先会想到下面这样一个写法

select distinct name from Sample order by DepartmentId

从语义上说,这是很自然的。但是很惋惜,这个语句根本没法履行,毛病消息是:

这个毛病的意思是,如果使用了DISTINCT(去重复值),则出现在OrderBy后面的字段,一定要也出现在SELECT后面,但如果DepartmentID如果也真的出现在SELECT后面,明显是不会有重复值的,所以结果肯定也是不对的。

select distinct name,DepartmentId from Sample order by DepartmentId

 

那末,既然DISINCT 与OrderBy结合起来用会有这个的一个问题,我们会不会有可能变通一下,例以下面这样:

SELECT distinct a.Name
FROM (select top 100 percent name from Sample order by DepartmentId) a

想比较之前的写法,我们用到了子查询技术。一样从语义上看,仍热是很直观明了的。我想先依照DepartmentId进行排序, 然后再去重复值。但是返回到结果是下面这样的:

虽然确切去除重复值,但返回的顺序却是不对的。我们希望是先依照DepartmentId排序以后,然后去除重复值,并且保存排序后的相对顺序。

为何会出现上面这个结果呢?实际上是由于DISTINCT本身是会做排序的,而且这个行动是没法更改的(下图的履行计划中可以看到这一点)。所以其实我们之前做的Order by在这里会失去意义。【实际上,如果视察ADO.NET Entity Framework等ORM工具中生成的类似的一个查询,它会自动抛弃Order by的设置】

那末,这样的情况下,是不是是就不可能实现需求了呢?虽然说,这个需求其实不多见,绝大部份时候,DISTINCT作为最后一个操作,做一次排序是合乎情理的。

我是这样斟酌到,既然DISTINCT的这个行动是内置的,那末会不会可以绕过这个操作呢?终究我用的一个解决方案是:我能不能把每一个Name都编上一个编号,例如有两个A的话,第一个A我为它编号为1,第二个编号为2,以此类推。然后,查询的时候,我先排序,然后挑选那些编号为1的Name,这样其实也就实现了去重复值了。

SQL Server 2005开始提供了一个ROW_NUMBER的功能,结合这个功能,我实现了下面这样的查询:

select a.Name from
(select top 100 percent
Name,DepartmentId,ROW_NUMBER() over(partition by name order by departmentid) row
from Sample order by DepartmentId) a
where a.row=1
order by a.DepartmentId

然后,我得到了下面这样的结果,我斟酌下来,这应当是符合了之条件到的这个需求的

相比较而言,这个查询的效力会低一些,这个是可以预感的(可以通过下图看出一点端倪)。但如果需求是硬性的,那末牺牲一些性能也是不奇怪的。固然,我们可以再研究看看会不会有更优的一些写法。不管如何,使用内置标准的实现,通常都是相对较快的。

本篇文章到此结束,如果您有相关技术方面疑问可以联系我们技术人员远程解决,感谢大家支持本站!

文章来源:丸子建站

文章标题:针对distinct疑问引发的一系列思考

https://www.wanzijz.com/view/61801.html

X

截屏,微信识别二维码

微信号:weimawl

(点击微信号复制,添加好友)

打开微信