具有内部联接的SQL Server返回的结果超出预期

时间:2019-05-10 18:14:54

标签: sql sql-server tsql

我有这个SQL查询:

SELECT 
    us.userid, 
    us.username, 
    CONVERT(VARCHAR(10), s.created, 101) AS LastLoginDate 
FROM
    users us 
INNER JOIN 
    session s ON us.userid = s.userid 
WHERE  
    supergroupid = 145577 
ORDER BY 
    us.userid DESC 

现在,由于每个用户在会话表中有多个会话条目,因此每个用户获得多个(重复)结果。

如何从每个用户获取会话表中最新创建的条目,如何仅从用户表中获取一个条目以及其他数据?

7 个答案:

答案 0 :(得分:0)

已被问及回答了数百次。但是,编写解决方案的代码比找到重复的代码容易。另外,您实际上不应该在查询中设置日期格式。这应该在表示层中完成。

select *
from
(
    SELECT us.userId, us.userName, CONVERT(VARCHAR(10),s.created, 101) as LastLoginDate
        , RowNum = ROW_NUMBER() over (partition by us.userId order by s.created desc)
      FROM users us
    inner join session s 
      on us.userId = s.userId
      where superGroupId = 145577
) x
where x.RowNum = 1
order by x.userid desc

答案 1 :(得分:0)

我认为在日期上具有Max()的Group By会起作用:

SELECT us.userId, us.userName, MAX(CONVERT(VARCHAR(10),s.created, 101)) as LastLoginDate
  FROM users us
inner join session s 
  on us.userId = s.userId
  where superGroupId = 145577
  group by us.userId, us.userName
  order by us.userid desc

答案 2 :(得分:0)

您可以执行一个子查询,该子查询返回每个用户的最新会话并像这样加入:

SELECT us.userId, us.userName, CONVERT(VARCHAR(10),s.created, 101) as LastLoginDate
FROM users us
INNER JOIN
(
    SELECT s.userId, s.created, ROW_NUMBER OVER(PARTITION BY s.userId ORDER BY s.created DESC) AS [RowNum]
    FROM session AS s


) s 
  on us.userId = s.userId
  where superGroupId = 145577 AND s.[RowNum] = 1
  order by us.userid desc

答案 3 :(得分:0)

如果要使用最近会话的日期/时间,请使用max()。但是之前转换为字符串!

select us.userId, us.userName, convert(varchar(10), max(s.created), 101) as LastLoginDate
from users us inner join
     session s 
     on us.userId = s.userId
where superGroupId = 145577
group by us.userid, us.userName;

答案 4 :(得分:0)

使用此查询:

SELECT userId, MAX(created) as LastLoginDate
FROM session
GROUP BY userId 

您将获得每个用户的最后登录日期。
然后将其连接到表users

SELECT us.userId, us.userName, CONVERT(VARCHAR(10), s.LastLoginDate, 101) as LastLoginDate
FROM users us INNER JOIN (
    SELECT userId, MAX(created) as LastLoginDate
    FROM session
    GROUP BY userId 
) s on s.userId = us.userId 
WHERE superGroupId = 145577
ORDER BY us.userid desc

答案 5 :(得分:0)

由于没有人提及它,所以我真的很喜欢使用公用表表达式(CTE),我认为这有助于提高可读性。

;WITH ctelastlogin (userid, lastlogindate) 
     AS (SELECT userid, 
                Max(created) 
         FROM   session 
         GROUP  BY userid) 
SELECT us.userid, 
       us.username, 
       CONVERT(VARCHAR(10), cte.lastlogindate, 101) AS LastLoginDate 
FROM   users us 
       INNER JOIN ctelastlogin cte 
               ON cte.userid = us.userid 
WHERE  supergroupid = 145577 
ORDER  BY us.userid DESC 

答案 6 :(得分:0)

您可以rank进行每个会话,然后根据最新的会话进行过滤。

类似...

SELECT * FROM (
SELECT DENSE_RANK() OVER (PARTITION BY US.USERID ORDER BY LASTLOGINDATE DESC) RNK
)
WHERE RNK = 1