Tengo esta consulta 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 

Ahora, dado que hay varias entradas de sesión en la tabla de sesión por usuario, obtengo múltiples resultados (duplicados) por usuario.

¿Cómo puedo obtener solo la entrada más reciente creada en la tabla de sesión por usuario, solo una entrada junto con los otros datos de la tabla de usuarios?

-1
Laziale 10 may. 2019 a las 21:14

7 respuestas

La mejor respuesta

Esto ha sido preguntado y respondido cientos de veces. Pero fue más fácil codificar una solución que encontrar un duplicado. Además, realmente no debe formatear su fecha en su consulta. Eso debe hacerse en la capa de presentación.

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
0
Sean Lange 10 may. 2019 a las 18:21

Con esta consulta:

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

Obtienes la última fecha de inicio de sesión para cada usuario.
Luego únala a la tabla 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
forpas 10 may. 2019 a las 18:25

Puede realizar una subconsulta que devuelve la sesión más reciente para cada usuario y unirse de esa manera:

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
Ryan Wilson 10 may. 2019 a las 18:21

Si desea la fecha / hora de la sesión más reciente, use max(). ¡Pero antes la conversión a una cadena!

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
Gordon Linoff 10 may. 2019 a las 18:25

Puede rank cada sesión y luego filtrar en la última.

Hemos detectado un problema desconocido.

SELECT * FROM (
SELECT DENSE_RANK() OVER (PARTITION BY US.USERID ORDER BY LASTLOGINDATE DESC) RNK
)
WHERE RNK = 1
0
Mr John 10 may. 2019 a las 19:18

Como nadie lo mencionó todavía, realmente me gusta usar una expresión de tabla común (CTE) que creo que ayuda con la legibilidad.

;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
betelgeuce 11 may. 2019 a las 04:07

Creo que un Group By con un Max () en la fecha funcionaría:

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
wavery 10 may. 2019 a las 18:21