鉴于下面的查询,dps_markers 中可能有多行具有相同的标记键,但我们只想加入第一行。如果我接受这个查询并删除前 1 和 ORDER BY,我会得到一个 mbg.marker_value 的值,但按原样运行它总是返回 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'
使用 OUTER APPLY 而不是 LEFT JOIN:
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';
与 JOIN 不同,APPLY 允许您在内部查询中引用 u.id。
调试此类情况的关键是自行运行子查询/内联视图以查看输出是什么:
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
运行它,您会看到 profile_id
值与 u162231993
的 u.id
值不匹配,这可以解释为什么任何 mbg
引用都会返回 null
(感谢左连接;您不会如果它是内部连接,则不会得到任何东西)。
您已经使用 TOP
将自己编码到一个角落,因为现在如果您想为其他用户运行它,您必须调整查询。更好的方法是:
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'
这样,您可以更改 where
子句中的 id
值以检查系统中任何用户的记录。
因为有序子查询中的 TOP 1
没有 profile_id = 'u162231993'
Remove where u.id = 'u162231993'
然后查看结果。
单独运行子查询以了解发生了什么。
达米尔是对的,
您的子查询需要确保 dps_user.id 等于 um.profile_id,否则它将抓取可能但可能不等于您的 'u162231993' id 的顶行
您的查询应如下所示:
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'
WHERE um.profile_id = 'u162231993'
放在子查询中,将 WHERE mbg.marker_value IS NOT NULL
放在外面。
@SearchFor = 'u162231993'
,然后在 WHERE
中使用它,或者发布一些数据和表结构,以便其他人可以帮助并尝试一下。