sql server - right - Top 1 con una combinación izquierda
sql substring hasta un caracter (4)
Dada la siguiente consulta, puede haber varias filas en dps_markers con la misma clave de marcador, pero solo queremos unirnos contra la primera. Si tomo esta consulta y elimino el top 1 y ORDER BY obtengo un valor para mbg.marker_value pero lo ejecuto como está, siempre devuelve null
SELECT u.id, mbg.marker_value
FROM dps_user u
LEFT JOIN
(SELECT TOP 1 m.marker_value, um.profile_id
FROM dps_usr_markers um (NOLOCK)
INNER JOIN dps_markers m (NOLOCK)
ON m.marker_id= um.marker_id AND
m.marker_key = ''moneyBackGuaranteeLength''
ORDER BY m.creation_date
) MBG ON MBG.profile_id=u.id
WHERE u.id = ''u162231993''
Damir está en lo correcto,
Su subconsulta necesita asegurarse de que dps_user.id sea igual a um.profile_id, de lo contrario tomará la fila superior que podría, pero probablemente no será igual a su id de ''u162231993''
Su consulta debería verse así:
SELECT u.id, mbg.marker_value
FROM dps_user u
LEFT JOIN
(SELECT TOP 1 m.marker_value, um.profile_id
FROM dps_usr_markers um (NOLOCK)
INNER JOIN dps_markers m (NOLOCK)
ON m.marker_id= um.marker_id AND
m.marker_key = ''moneyBackGuaranteeLength''
WHERE u.id = um.profile_id
ORDER BY m.creation_date
) MBG ON MBG.profile_id=u.id
WHERE u.id = ''u162231993''
La clave para depurar situaciones como esta es ejecutar la subconsulta / vista en línea para ver cuál es el resultado:
SELECT TOP 1
dm.marker_value,
dum.profile_id
FROM DPS_USR_MARKERS dum (NOLOCK)
JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id
AND dm.marker_key = ''moneyBackGuaranteeLength''
ORDER BY dm.creation_date
Al ejecutar eso, vería que el valor de u162231993
no coincide con el valor de u162231993
de u162231993
, lo que explicaría por qué cualquier referencia de mbg
devolvería null
(gracias a la combinación de la izquierda; no obtendría nada si fuera un interno unirse).
Te has codificado en una esquina usando TOP
, porque ahora tienes que modificar la consulta si deseas ejecutarla para otros usuarios. Un mejor enfoque sería:
SELECT u.id,
x.marker_value
FROM DPS_USER u
LEFT JOIN (SELECT dum.profile_id,
dm.marker_value,
dm.creation_date
FROM DPS_USR_MARKERS dum (NOLOCK)
JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id
AND dm.marker_key = ''moneyBackGuaranteeLength''
) x ON x.profile_id = u.id
JOIN (SELECT dum.profile_id,
MAX(dm.creation_date) ''max_create_date''
FROM DPS_USR_MARKERS dum (NOLOCK)
JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id
AND dm.marker_key = ''moneyBackGuaranteeLength''
GROUP BY dum.profile_id) y ON y.profile_id = x.profile_id
AND y.max_create_date = x.creation_date
WHERE u.id = ''u162231993''
Con eso, puede cambiar el valor de id
en la cláusula where
para verificar los registros de cualquier usuario en el sistema.
Porque el TOP 1
de la profile_id = ''u162231993''
ordenada no tiene profile_id = ''u162231993''
Quite where u.id = ''u162231993''
y vea los resultados.
Ejecute la subconsulta por separado para comprender qué está pasando.
Utilice APLICACIÓN EXTERIOR en lugar de APUESTA IZQUIERDA:
SELECT u.id, mbg.marker_value
FROM dps_user u
OUTER APPLY
(SELECT TOP 1 m.marker_value, um.profile_id
FROM dps_usr_markers um (NOLOCK)
INNER JOIN dps_markers m (NOLOCK)
ON m.marker_id= um.marker_id AND
m.marker_key = ''moneyBackGuaranteeLength''
WHERE um.profile_id=u.id
ORDER BY m.creation_date
) AS MBG
WHERE u.id = ''u162231993'';
A diferencia de JOIN, APPLY le permite hacer referencia al u.id dentro de la consulta interna.