0

我有一个对性能非常敏感的 SQL Server 数据库。我需要对以下问题做出有效的选择:

我有一个包含 4 个字段的简单表格:

ID [int, PK]
UserID [int, FK]
Active [bit]
GroupID [int, FK]

每个 UserID 可以在 Active='false' 的 GroupID 中出现多次(以及在多个 groupID 中),但在 Active='true' 时只能出现一次。

如:

(id,userid,active,groupid)
1,2,false,10
2,2,false,10
3,2,false,10
4,2,true,10

我需要从某个组中的表中选择所有不同的用户,它应该保存用户的最后一个活动状态。如果用户处于活动状态 - 它不应该返回用户的非活动状态,如果它在某个时间点是这样的。

天真的解决方案是双重选择 - 一个选择所有活动用户,然后一个选择所有未出现在第一个选择语句中的非活动用户(因为每个用户可能在某个时间点处于非活动状态)。但这将运行第一个选择(与活动用户一起)两次 - 这是非常不需要的。

有没有什么聪明的方法可以只做一个选择来获得所需的查询?想法?

提前谢谢了!

4

5 回答 5

0

不确定我是否理解您希望查询返回的内容,但无论如何。此查询将为您提供在最后一个条目中处于活动状态的组中的用户。它使用row_number(),因此您至少需要 SQL Server 2005。

表定义:

create table YourTable
(
  ID int identity primary key,
  UserID int,
  Active bit,
  GroupID int
)

支持查询的索引:

create index IX_YourTable_GroupID on YourTable(GroupID) include(UserID, Active)

样本数据:

insert into YourTable values
(1, 0, 10),
(1, 0, 10),
(1, 0, 10),
(1, 1, 10),
(2, 0, 10),
(2, 1, 10),
(2, 0, 10),
(3, 1, 10)

询问:

declare @GroupID int = 10

;with C as 
(
  select UserID,
         Active,
         row_number() over(partition by UserID order by ID desc) as rn
  from YourTable as T
  where T.GroupID = @GroupID
)
select UserID
from C
where rn = 1 and
      Active = 1

结果:

UserID
-----------
1
3
于 2011-10-03T05:56:02.303 回答
0

尝试这个:

Select
   ug.GroupId,
   ug.UserId,
   max(ug.Active) LastState
from
   UserGroup ug
group by
   ug.GroupId,
   ug.UserId

如果用户/组组合的活动字段设置为 1,您将获得 1,否则您将获得最后状态的 0。

于 2011-10-02T14:37:24.193 回答
0

像这样的视图怎么样:

createview ACTIVE as select * from USERS where Active = TRUE

然后从该视图中选择一个就足够了:

select user from ACTIVE where ID ....
于 2011-10-02T14:13:16.240 回答
0

我不喜欢以您的方式使用“isActive”列。这需要两个UPDATEs 来更改活动状态,并且具有在不同记录中多次存储有关活动状态的信息的效果。

相反,我会删除该active字段并执行以下两件事之一:

  1. 如果您已经在某个地方有一个表,其中(userid, groupid)(或可能是)aPRIMARY KEYUNIQUE INDEX然后将该active列添加到该表中。当用户对特定组变得活跃或不活跃时,使用true或仅更新该单个记录false

  2. 如果这样的表尚不存在,则使用“(userid,groupid)as thePRIMARY KEY active”创建一个,and the field然后按上述方式处理该表。

无论哪种情况,您只需要查询此表(无需聚合)即可确定用户相对于特定组的状态。同样重要的是,您只需存储一次trueorfalse值,并且只需要UPDATE一个值来更改状态。最后,此表充当您可以存储特定于该用户在该组中的成员身份的其他信息的地方,这些信息仅适用于每个成员身份,而不是每个状态更改一次。

于 2011-10-02T15:28:18.387 回答
0

尝试这个:

SELECT t.* FROM tbl t 
INNER JOIN (
    SELECT MAX(id) id
    FROM tbl
    GROUP BY userid 
) m
ON t.id = m.id 
于 2011-10-02T20:30:29.517 回答