需要一些关于简单SQL查询的帮助吗
我有一个将状态信息转储到数据库的游戏。例如,连接、断开连接、抓取屏幕转储等 每个状态都由一个名为需要一些关于简单SQL查询的帮助吗,sql,tsql,Sql,Tsql,我有一个将状态信息转储到数据库的游戏。例如,连接、断开连接、抓取屏幕转储等 每个状态都由一个名为StateTypeId的字段定义,该字段是简单查找表'StateTypes'的外键 现在,我正试图找到所有当前已连接的人(例如StateTypeId==1),但我不确定该怎么做。当我说当前已连接时,我的意思是用户没有“LostConnection”状态(即StateType==2)作为其最新条目 我当时在想一件事 SELECT UserId FROM UserData WHERE StateType
StateTypeId
的字段定义,该字段是简单查找表'StateTypes'
的外键
现在,我正试图找到所有当前已连接的人(例如StateTypeId==1),但我不确定该怎么做。当我说当前已连接时,我的意思是用户没有“LostConnection
”状态(即StateType==2)作为其最新条目
我当时在想一件事
SELECT UserId
FROM UserData
WHERE StateType = 1
GROUP BY UserId
或
但这会返回所有结果,而不仅仅是最新的结果
有什么建议吗
(我猜我缺少了一个TOP(1)
和一些排名/顺序?)
编辑
啊!我忘了提到,我在表->DateEntered中有一个DateTime列
编辑2-澄清问题和一些样本数据。
我尝试了建议的解决方案,但运气不太好。因此,我将提供一些示例数据,看看这是否有助于澄清我的问题
ID State UserName DateAdded
1 Connected Foo 1/1/2000 12:00
2 Connected Bar 1/1/2000 12:01
3 ScreenShot Foo 1/1/2000 12:05
4 LostConnection Foo 1/1/2000 12:06
5 Connected Joe 1/1/2000 12:10
6 LostConnection Joe 1/1/2000 12:15
7 Screenshot Bar 1/1/2000 12:16
8 Connected Jane 1/1/2000 12:22
所以从这个角度来看,(目前)有联系的人是Bar和Jane。福和乔走了。还要注意,Bar的最后一个活动是一个屏幕截图,这意味着,他的最后一个活动不是一个LostConnection状态
HTH.您要查找的是StateType为1或2的“最近”条目: 然后,您需要为每个用户确定“最后一个”:
select UserName, max(DateAdded) as LastDate
from UserData
where State IN ('Connected', 'LostConnection')
Group by UserName
然后需要检查这些表的状态(这需要与原始表连接):
另一种加入方式是使用UserData的id,如下所示:
SELECT UserName
FROM UserData allData join
(select max(id) as id -- if ids are assigned in ascending order
from UserData
where State IN ('Connected', 'LostConnection')
Group by UserName) as lastData on allData.id = lastData.id
WHERE StateType = 'Connected'
您要查找的是StateType为1或2的“最近”条目: 然后,您需要为每个用户确定“最后一个”:
select UserName, max(DateAdded) as LastDate
from UserData
where State IN ('Connected', 'LostConnection')
Group by UserName
然后需要检查这些表的状态(这需要与原始表连接):
另一种加入方式是使用UserData的id,如下所示:
SELECT UserName
FROM UserData allData join
(select max(id) as id -- if ids are assigned in ascending order
from UserData
where State IN ('Connected', 'LostConnection')
Group by UserName) as lastData on allData.id = lastData.id
WHERE StateType = 'Connected'
您将需要一个timestamp列,并且需要编写一个将表与自身连接起来的查询,如下所示
Select *
From Userdata U
Where 1 = (Select Top 1 StateType
From Userdata U2
Where U.UserId = U2.UserId
order by u2.TimeStamp desc)
您将需要一个timestamp列,并且需要编写一个将表与自身连接起来的查询,如下所示
Select *
From Userdata U
Where 1 = (Select Top 1 StateType
From Userdata U2
Where U.UserId = U2.UserId
order by u2.TimeStamp desc)
如果您有datetime条目或时间戳,可以通过以下方式执行:
Select UserID
From UserData
Where StateType = 1
Group by UserID
Having Date = Max(Date)
如果您有datetime条目或时间戳,可以通过以下方式执行:
Select UserID
From UserData
Where StateType = 1
Group by UserID
Having Date = Max(Date)
我认为值得测试一个不存在的方法的性能 i、 e.查找具有适当StateType且没有较新记录的用户
SELECT UD1.UserId
FROM UserData AS UD1
WHERE UD1.StateType = 1
AND NOT EXISTS
(
-- Check for newer records:
SELECT *
FROM UserData AS UD2
WHERE UD2.DateEntered > UD1.DateEntered
)
如果它们有许多行存储在UserData中,并且/或者您将它们保存了很长一段时间,那么这种方法的性能可能会很差
如果是这种情况,并且这是一个频繁发生的查询,我将创建一个UserCurrentState表(columns=UserId,StateType),当StateType更改时更新该表(我将在UserData表上放置触发器以强制执行此操作)
UserData中的StateType索引不够好,无法发挥作用。您可以有一个包含DateEntered、StateType和UserId的索引,该索引将覆盖查询,因此应该使用该索引,但实际上,只有在您可以限制检查的DateEntered范围的情况下,该索引才有帮助。如果你只寻找最后一个小时/天,那么如果你从一开始就在寻找,那么它不会有多大帮助。我认为值得测试一种不存在的方法的性能 i、 e.查找具有适当StateType且没有较新记录的用户
SELECT UD1.UserId
FROM UserData AS UD1
WHERE UD1.StateType = 1
AND NOT EXISTS
(
-- Check for newer records:
SELECT *
FROM UserData AS UD2
WHERE UD2.DateEntered > UD1.DateEntered
)
如果它们有许多行存储在UserData中,并且/或者您将它们保存了很长一段时间,那么这种方法的性能可能会很差
如果是这种情况,并且这是一个频繁发生的查询,我将创建一个UserCurrentState表(columns=UserId,StateType),当StateType更改时更新该表(我将在UserData表上放置触发器以强制执行此操作)
UserData中的StateType索引不够好,无法发挥作用。您可以有一个包含DateEntered、StateType和UserId的索引,该索引将覆盖查询,因此应该使用该索引,但实际上,只有在您可以限制检查的DateEntered范围的情况下,该索引才有帮助。如果您只寻找最后一个小时/天,那么如果您从一开始就在寻找,那么它不会有多大帮助。实际上,这可能会更有效(SQL Server 2005以后)
实际上,这可能更有效(SQL Server 2005以后)
下面是另一个可能的解决方案,尽管使用
的解决方案不存在
可能会执行得更好
SELECT U1.*
FROM UserData U1
LEFT OUTER JOIN UserData U2
ON (U1.UserName = U2.UserName
AND U1.DateAdded < U2.DateAdded
AND U2.StateType IN (1,2))
WHERE U1.StateType = 1
AND U2.UserName IS NULL
ORDER BY U1.DateAdded DESC;
选择U1*
从用户数据U1
左外部联接用户数据U2
打开(U1.UserName=U2.UserName
和U1.DateAdded
这里有另一种可能的解决方案,尽管使用的解决方案不存在
可能会执行得更好
SELECT U1.*
FROM UserData U1
LEFT OUTER JOIN UserData U2
ON (U1.UserName = U2.UserName
AND U1.DateAdded < U2.DateAdded
AND U2.StateType IN (1,2))
WHERE U1.StateType = 1
AND U2.UserName IS NULL
ORDER BY U1.DateAdded DESC;
选择U1*
从用户数据U1
左外部联接用户数据U2
打开(U1.UserName=U2.UserName
和U1.DateAdded
UserData中还有哪些列?Oops。我忘了提到DateTime列:)Edited inital post.Mabye这是显而易见的,但是如果您经常执行此查询并且有很多状态更改,那么您最好将最后一个状态反规范化到UserData表中。优点:查询更容易/更快。缺点:更新数据库更难/更慢(必须做两件事并且始终正确)听起来像是触发器的一个好用法…UserData中还有哪些列?Oops。我忘了提到DateTime列:)Edited inital post.Mabye这是显而易见的,但是如果您经常执行此查询并且有很多状态更改,那么您最好将最后一个状态反规范化到UserData表中。优点:查询更容易/更快。C