2009-05-31 74 views
1

在SQL Server中,如何实现选择多个字段(不带聚合函数)并将DISTINCT语句仅应用于一个特定字段?选择许多将DISTINCT应用于只有一个特定字段的字段

例如:如果我有哪里存储用户的动作表,伪模式会是这样的:

UserActions 
------------ 
id, 
User, 
Action 
insertDate 

我想给定用户的最新动作,而无需重复场“行动'?

例如,如果表中内容是:

1, john, update, 01/01/09 
2, john, update, 01/02/09 
3, john, update, 01/03/09 
4, john, delete, 01/04/09 
5, john, insert, 01/05/09 
6, john, delete, 01/06/09 

我想获得:

6, john, delete, 01/06/09 
5, john, insert, 01/05/09 
3, john, update, 01/03/09 

提前非常感谢。

+0

简短的答案是用DISTINCT无法做到的。从你的结果集看起来你正在返回MAX(insertDate) – spencer7593 2009-05-31 22:30:18

回答

5

内查询应选择最大号对于用户'john'的每个操作,外部查询将选择与内部查询中的id集合相匹配的那些记录,以便您只应获取指定用户的每个操作的最后一个。

select id, user, action, insertDate 
from userActions 
where id in (select max(id) 
       from userActions 
       where user ='john' 
       group by action) 
+0

? MAX是一个聚合函数。 – dkretz 2009-05-31 22:24:28

+0

非常好!谢谢! – 2009-05-31 22:28:44

0

不知道如何使用SQL来做到这一点。你可以做完整的查询(它看起来像你想通过InsertDate DESC排序),然后只提取你想要的手动。

set s = new set() 
while (has more results) { 
    var r = next result 
    if (!s.contains(r)) { 
     process result 
     s.add(r) 
    } 
} 
+0

这将比纯sql的答案慢,并且可能会返回许多额外的不必要的行 – 2009-06-01 17:49:01

0

如果你有一个固定的动作,您可以编写一个查询前各1和联合在一起的结果:

SELECT TOP 1 [id], [User], [InsertDate] 
FROM [UserActions] 
WHERE [Action] = 'insert' 
ORDER BY [InsertDate] DESC 

UNION 

SELECT TOP 1 [id], [User], [InsertDate] 
FROM [UserActions] 
WHERE [Action] = 'update' 
ORDER BY [InsertDate] DESC 

UNION 

SELECT TOP 1 [id], [User], [InsertDate] 
FROM [UserActions] 
WHERE [Action] = 'delete' 
ORDER BY [InsertDate] DESC 
+1

TOP 1与ORDER BY DESC实际上是一个聚合函数。 – dkretz 2009-05-31 22:23:50

1

一种选择值得考虑(在SQL Server 2008中,约SS 2005不知道):

SELECT id, User, Action, InsertDate 
FROM Table 
WHERE User = 'john' 
AND ROW_NUMBER() 
    OVER(PARTITION BY Action ORDER BY InsertDate DESC) 
    = 1 

(看,妈妈,没有聚合函数 - !)

1

忽略的OP需要对于没有聚合功能(仍不知道为什么...)

我与给定的答案的问题是:

  1. 它不是动态的允许任何其他用户 - 说''标记'
  2. 它假定动作的最大(id)将匹配最新动作 - 测试数据表明,但我不会假设作为一项规则。

所以与那些在心中更加动态的查询需要建立

2个加入到测试数据

7, john, update, 04/01/09 
8, mark, insert, 01/02/09 

多行的回答并没有给什么OP想要

这是我的第一次快速草稿 - 将整理后

select 
    userActions.id, 
    userActions.[user], 
    userActions.Action, 
    userActions.insertDate 

from 
userActions 
join 
    (
    select 
     [user], action, max(insertdate) as maxinsertdate 
    from userActions 
    group by 
     [user], action 
    ) aggsubquery 
    on userActions.[user] = aggsubquery.[user] 
     and userActions.action = aggsubquery.action 
     and userActions.insertdate = aggsubquery.maxinsertdate 

更新....

第二个版本使用的ID来获得不同的行那里可以由特定的用户,即是行动的一个以上的次数,如果测试数据也有以下行

9, john, delete, 06/01/09 

那么你会需要在第6行和第9行之间决定哪一个返回。我任意选择使用max(id),因为我猜数据很重要,而不是行号

select 
    max(userActions.id) as id, 
    userActions.[user], 
    userActions.Action, 
    userActions.insertDate 
from 
userActions 
join 
    (
    select 
     [user], action, max(insertdate) as maxinsertdate 
    from userActions 
    group by 
     [user], action 
    ) aggsubquery 
    on userActions.[user] = aggsubquery.[user] 
     and userActions.action = aggsubquery.action 
     and userActions.insertdate = aggsubquery.maxinsertdate 
group by 
    userActions.[user], 
    userActions.Action, 
    userActions.insertDate 
相关问题