今天被人问到这样一个问题,整理出来给大家也参考一下
假设有如下这样一张表格:
这里的数据,具有如下的特征:在一个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.NameFROM (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 percentName,DepartmentId,ROW_NUMBER() over(partition by name order by departmentid) rowfrom Sample order by DepartmentId) awhere a.row=1order by a.DepartmentId
然后,我得到了下面这样的结果,我推敲下来,这应该是符合了之前提到的这个需求的
相比较而言,这个查询的效率会低一些,这个是可以预见的(可以通过下图看出一点端倪)。但如果需求是硬性的,那么牺牲一些性能也是不奇怪的。当然,我们可以再研究看看是否有更优的一些写法。无论如何,使用内置标准的实现,通常都是相对较快的。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

WebStorm Mac版
好用的JavaScript开发工具

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

禅工作室 13.0.1
功能强大的PHP集成开发环境