SQL查询选择地理点

时间:2016-06-15 09:00:00

标签: sql-server tsql

我是SQL查询的新手,我需要获得一些活跃玩家的最后位置,这意味着他们的Play值等于1.我必须在表Events之间建立联接我有玩家活动的地方:

  • ID:唯一行ID
  • 时间戳:播放器将其状态更改为无效或再次激活的时间
  • PlayerId:此活动所针对的玩家的ID
  • 有效:1-Active,0-Inactive

使用表格Positions,其中所有玩家每隔2-3秒使用列位置:

  • PlayerId
  • 时间戳:收到职位的时间
  • 位置:收到位置的地理位置

以获取活跃玩家的当前纬度和经度。

我当前的查询:

select 
    e.PlayerId, e.Active,
    p.Location.Lat, p.Location.Long,
    max_date = max(e.Timestamp),
    max_date2 = max(p.Timestamp)
from
    Events e 
inner join 
    Positions p on e.PlayerId = p.PlayerId 
where 
    e.Active= 1
group by 
    e.PlayerId, e.Active, p.Location.Lat, p.Location.Long

但不是返回2行我得到更多。我想这是因为group by子句中的b.Location.Lat, b.Location.Long字段,因为简单查询:

select 
    e.PlayerId, e.Active,
    max_date = max(e.Timestamp),
    max_date2 = max (p.Timestamp)
from 
    Events e 
inner join 
    Positions p on e.PlayerId = p.PlayerId 
where 
    e.Active = 1
group by 
    e.PlayerId, e.Active

返回正确的2行,但我还需要获取Lat-Long列。

更新 我在查询中发现了一个问题。当我再次针对不同的值运行它时,我已经看到它返回所有玩家的位置,如果他们甚至只有一次活动,之后他们就变得不活跃。但是,如果一个用户的Active的最后一个值(根据最大时间戳)为0,则查询应从响应中删除播放器位置。

有没有什么办法可以添加这些列而不会获得比所需更多的行?

1 个答案:

答案 0 :(得分:1)

您可以将当前查询包装在外部查询中,然后再次加入到您的位置表。像这样的东西;

SELECT
base.PlayerId
,base.Active
,base.max_date
,base.max_date2
,p.Location.lat
,p.Location.long
FROM
(
    SELECT a.PlayerId ,
       a.Active,
       max_date = max( a.Timestamp ),
       max_date2 = max (b.Timestamp)
    FROM Events a 
    INNER JOIN Positions b 
        ON a.PlayerId =b.PlayerId 
    WHERE a.Active= 1
    GROUP BY a.PlayerId , a.Active
) base
JOIN Positions p
    ON base.PlayerId = p.PlayerId
    AND base.max_date2 = p.Timestamp

您的其他查询无效的原因是您要为每个lat& amp;长点。这样做会为您提供您之后的唯一列表,然后再次加入Positions以获取lat长信息。

编辑:根据评论,如果要排除最新Active值设置为零的任何人,请将其添加到代码的末尾;

JOIN
(
    SELECT
    e.PlayerID
    ,MAX(e.Timestamp) Timestamp
    FROM Events e
    GROUP BY e.PlayerID
) latest
ON base.PlayerID = latest.PlayerID
JOIN Events e2
ON latest.PlayerID = e2.PlayerID
AND latest.Timestamp = e2.Timestamp

WHERE e2.Active <> 0