2016-09-30 26 views
0

我在网上查找了解决此问题的解决方案,但似乎无法找到我正在查找的内容。查询使用具有优先级的多个列上的最小聚合函数

可以说,我们有一个表,看起来像这样:

_____________________________________________________ 
| id (PK) | name | date  | ... other data ... | 
----------------------------------------------------- 
| 1 | BOB | 2016-11-20 |  .... 
--------------------------------  
| 3 | CARL | 2015-09-02 |  .... 
-------------------------------- 
| 4 | BOB | 2016-11-18 |  .... 
-------------------------------- 
| 5 | JON | 2016-03-03 |  .... 
-------------------------------- 
| 6 | TIM | 2016-11-24 |  .... 
-------------------------------- 
| 7 | TIM | 2016-11-24 |  .... 
-------------------------------- 
| 8 | JON | 2016-05-05 |  .... 
-------------------------------- 

我需要一个查询,将:
1.每个返回名称的不同列表(不同的函数)
2名称有最早的日期(min函数)
3. id与上述两列一起。
4.如果日期是相同的,使用分钟(ID),以此来决定选择

所以在这种情况下,所期望的结果是这样的哪一行..

_____________________________________________________ 
| id (PK) | name | date | ... other data ... | 
----------------------------------------------------- 
| 3 | CARL | 2015-09-02 |  .... 
-------------------------------- 
| 4 | BOB | 2016-11-18 |  .... 
-------------------------------- 
| 5 | JON | 2016-03-03 |  .... 
-------------------------------- 
| 6 | TIM | 2016-11-24 |  .... 
-------------------------------- 

是有没有一种方法可以在查询中有效地执行此操作,而无需创建临时表并使用脚本循环使用它?

这让我的一半的方式有:
SELECT DISTINCT(名称),分(日期),......其他数据...从表1


当我申请的分功能ID尽管它不像我需要的那样行事。在BOB的情况下,它混​​合两行,并返回1'id'和'2016-11-18'的日期 - 这是完全不正确的

任何帮助,非常感谢。

回答

0
;WITH cte AS (
    SELECT * 
     ,ROW_NUMBER() OVER (PARTITION BY name ORDER BY Date, Id) as RowNum 
    FROM 
     @Table 
) 

SELECT * 
FROM 
    cte 
WHERE 
    RowNum = 1 

所以,如果你认为它稍有不同。您需要每个名称的最早日期行。因此,如果您创建partitioned ROW_NUMBER()按日期升序排序,然后选择ROW_NUMBER() = 1您将得到您的答案。有些方法也可以通过聚合来完成。如果日期与Tim的情况相同,您也可以按顺序添加标识。

1

SQL Server 2005及更高版本支持窗口功能和row_number可能会非常有用。这个或者非常相似的东西应该可以工

SELECT 
    name 
    ,date 
    ,id 
from (-- Can't reference the windowing function within it's own select, 
     -- so we make it a subquery 
     select 
      name 
     ,date 
     ,id 
     ,row_number() over (partition by name order by date, id) Ranking 
     from Table1 
    ) sub 
where Ranking = 1 
order by name