选择列的不同和按日期列的顺序,但不显示日期列

时间:2014-08-11 07:57:21

标签: sql sql-server

以下简单查询将返回结果,其中包含按日期排序的名称和日期。

SELECT  DISTINCT Name, Date
FROM    dbo.Table WITH(NOLOCK)
ORDER BY DATE

结果

 Name  |     Date  
 --------------------
   a   |  31-Jul-2013  
   a   |  31-Aug-2013  
   a   |  30-Sep-2013  
   b   |  31-Oct-2013  
   b   |  30-Nov-2013  
   a   |  31-Dec-2013  

我如何只选择不同的名称,但名称的顺序必须按日期排序?

新结果

 Name  
  a  
  b  
  a

2 个答案:

答案 0 :(得分:2)

尝试此查询:

WITH Names AS (
   SELECT
      Name,
      Seq = Dense_Rank() OVER (ORDER BY SomeDate)
         - Dense_Rank() OVER (PARTITION BY Name ORDER BY SomeDate)
   FROM
      dbo.Names
)
SELECT Name
FROM Names
GROUP BY Name, Seq
ORDER BY Min(Seq)
;

<强> Run this live in a SQL Fiddle

这将返回您请求的A,B,A模式。

您无法使用简单的DISTINCT,因为您要求显示单个值,而是按所有排序该值可能与之关联的日期。如果您的数据看起来像这样怎么办?

Name  Date
----  ----
A     2014-01-01
B     2014-02-01
B     2014-03-01
A     2014-04-01

如何根据日期的某个理论排序决定是先将A放在第一位,还是以B为先?

这就是为什么我不得不做上面的窗口函数减法,它应该按你想要的顺序排列。

备注

我将此技术称为&#34;模拟PREORDER BY&#34;。 Dense_Rank在排序之前没有提供任何预先排序行的方法。如果您可以Dense_Rank() OVER (PREORDER BY Date ORDER BY Name)表示您希望首先按Date订购,但又不希望它成为结果排名计算的一部分,那么您将被设置!但是,这并不存在。经过一段时间的研究后,我想到了使用窗口函数组合来实现目的的想法,上面的查询代表了结果。

请注意,您还必须<{em> GROUP BY Name,而不仅仅是生成的减去窗口表达式,以便一切正常工作,因为表达式是唯一的另一列(在本例中为Name)可能导致整个集合中出现重复值(两个不同的值Names可以具有相同的表达式结果)。如果需要可以单独订购的值,您可以指定新的排名或其他窗口函数。

答案 1 :(得分:0)

我认为公用表表达式(CTE)可以在这里工作:

with cte as(
SELECT  DISTINCT Name, Date
FROM    dbo.Table WITH(NOLOCK)
ORDER BY DATE
)
select Name 
from cte 
order by Date