2009-08-16 11 views
6

Chicos, tengo una consulta donde básicamente selecciono el último navegador que usó nuestro usuario.Seleccione uno superior de la combinación externa izquierda

aquí es nuestra estructura (simplificado) tabla

HITS_TABLE 
---------- 
USERID 
BROWSER 
HITSDATE 

USER_TABLE 
---------- 
USERID 
USERNAME 

y aquí es cómo consultar la última versión del navegador que utiliza nuestro usuario

SELECT U.*, H.BROWSER 

FROM USER_TABLE U 

CROSS APPLY 
    (SELECT TOP 1 BROWSER 
    FROM HITS_TABLE 
    WHERE HITS_TABLE.USERID = U.USERID 
    ORDER BY HITS_TABLE.HITSDATE DESC 
)as H 

El HITS_TABLE simplemente se añade hace varios días.

Por lo tanto, esa consulta solo corresponde a los usuarios que visitaron nuestro sitio web después de que agregamos el HITS_TABLE y elimine los otros.

Aquí es el caso de la muestra

USER_TABLE 
------------------- 
USERID  USERNAME 
------------------- 
1   'Spolski' 
2   'Atwoord 
3   'Dixon' 


HITS_TABLE 
------------------------------ 
USERID  HITSDATE  BROWSER 
------------------------------ 
2   15/8/2009 'Firefox 3.5' 
1   16/8/2009 'IE 6' 
2   16/8/2009 'Chrome' 

Aquí es el resultado de la muestra

------------------------------ 
USERID  USERNAME  BROWSER 
------------------------------ 
1   'Spolsky' 'IE 6' 
2   'Atwoord' 'Chrome' 

Pero, quiero añadir otros usuarios con el navegador 'desconocido'. aquí está mi resultado deseado

------------------------------ 
USERID  USERNAME  BROWSER 
------------------------------ 
1   'Spolsky' 'IE 6' 
2   'Atwoord' 'Chrome' 
3   'Dixon'  'Unknown' 

creo que podría lograrse mediante la combinación externa izquierda. Pero siempre tuve esta: (no quiero que este resultado)

------------------------------ 
USERID  USERNAME  BROWSER 
------------------------------ 
1   'Spolsky' 'IE 6' 
2   'Atwoord' 'Chrome' 
2   'Atwoord' 'Firefox 3.5' 
3   'Dixon'  'Unknown' 

espero que mi pregunta es clara.

Respuesta

6

utilizando un grupo de ID de usuario en contra de la hits_table le permite obtener el máximo hitsdate() para cada ID de usuario. Llamé a este ÚLTIMO HITS en el código a continuación.

Al seleccionar en la TABLA DE USUARIO con una combinación izquierda en ÚLTIMOS TIEMPOS, puede extraer registros para cada usuario.

uniéndose de nuevo a HITS TABLE y luego allres le permite extraer el registro del navegador asociado con esa fecha, o un nulo para los usuarios que no tienen registro allí.

select 
    user_table.userid, 
    user_table.username, 
    isnull(hitstable.browser, 'unknown') as browser 
from 
    user_table 
left join 
(
    select 
    userid, 
    max(hitsdate) hitsdate 
    from 
    hits_table 
    group by 
    userid 
) latest_hits 
on 
    user_table.userid = latest_hits.userid  
left join 
    hits_table 
on hits.table.userid = latest_hits.userid 
and hits_table.hitsdate = latest_hits.hitsdate 
+2

Esta solución tiene en cuenta un hecho importante, que los otros faltan: ¿Qué sucede si la combinación de USERID e HITSDATE es ambigua, por ejemplo,? una fila adicional (2, 16/8/2009, 'Safari') existe? Usando las funciones de clasificación obtendría un resultado no determinista. ¿Puedes decir cuál es seleccionado? Esta solución proporcionaría ambas combinaciones, que en mi humilde opinión es mucho mejor. –

+0

Información adicional: para obtener información sobre el ranking de SQL Server, consulte http://msdn.microsoft.com/en-us/library/ms189798%28SQL.90%29.aspx –

+0

tiene razón. La función max() es muy útil para esto. gracias. pero creo que debería dejarse de lado. –

3

¿No podrías sub selecto, no es bonito pero debería funcionar ..

SELECT U.*, 

ISNULL((SELECT TOP 1 BROWSER 
    FROM HITS_TABLE 
    WHERE HITS_TABLE.USERID = U.USERID 
    ORDER BY HITS_TABLE.HITSDATE DESC),'UnKnown') AS Browser 

FROM USER_TABLE U 
+1

Si desea acceder a cualquier otra columna además del navegador de la tabla de aciertos en esta consulta, la selección secundaria no es para usted. En ese caso, describiría las soluciones de @rwarren y @gbn para ver cuál funciona mejor. @Mao tiene un punto interesante sobre los resultados no deterministas. Con su sombrero pragmático probablemente podría ignorar este caso extremo al agregarle tiempo a HITSDATE. –

0
SELECT U.*,'BROWSER' = 
    case 
    when (SELECT TOP 1 BROWSER FROM HITS_TABLE WHERE HITS_TABLE.USERID = U.USERID ORDER BY HITS_TABLE.HITSDATE DESC) is null then 'Unknown' 
else (SELECT TOP 1 BROWSER FROM HITS_TABLE WHERE HITS_TABLE.USERID = U.USERID ORDER BY HITS_TABLE.HITSDATE DESC) 
    end 
FROM USER_TABLE U 
+0

En su solución, ¿la sub selección no se ejecutará dos veces cuando el resultado no sea nulo? En primer lugar, para evaluar el "cuándo" y descubrir que el navegador no es nulo y, en segundo lugar, en el "else" para extraer el resultado. –

Cuestiones relacionadas