2009-05-31 70 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 
相關問題