SQL Server с внутренним объединением возвращает больше результатов, чем ожидалось - PullRequest
0 голосов
/ 10 мая 2019

У меня есть этот запрос 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 

Теперь, поскольку в таблице сеансов для каждого пользователя имеется несколько записей сеанса, я получаю несколько (дубликатов) результатов для пользователя.

Как я могу получить только самую последнюю запись s.created в таблице сеансов для пользователя, только одну запись вместе с другими данными из таблицы пользователей?

Ответы [ 7 ]

0 голосов
/ 10 мая 2019

Поскольку никто еще не упомянул об этом, мне действительно нравится использовать общее табличное выражение (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 
0 голосов
/ 10 мая 2019

Вы можете rank каждый сеанс, а затем фильтровать по последнему.

Что-то вроде ...

SELECT * FROM (
SELECT DENSE_RANK() OVER (PARTITION BY US.USERID ORDER BY LASTLOGINDATE DESC) RNK
)
WHERE RNK = 1
0 голосов
/ 10 мая 2019

С помощью этого запроса:

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
0 голосов
/ 10 мая 2019

Если вы хотите указать дату / время самого последнего сеанса, используйте 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;
0 голосов
/ 10 мая 2019

Вы можете выполнить подзапрос, который возвращает самый последний сеанс для каждого пользователя, и присоединиться к нему следующим образом:

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
0 голосов
/ 10 мая 2019

Я думаю, что Group By с Max () на дату будет работать:

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
0 голосов
/ 10 мая 2019

Об этом спрашивали и отвечали сотни раз. Но было проще написать решение, чем найти дубликат. Кроме того, вам действительно не следует форматировать дату в своем запросе. Это должно быть сделано на уровне представления.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...