带有左连接的 Top 1
鉴于下面的查询,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'
Given the query below there might be multiple rows in dps_markers with the same marker key but we only want to join against the first. If I take this query and remove the top 1 and ORDER BY I get a value for mbg.marker_value but run as it is it always returns 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'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用 OUTER APPLY 而不是 LEFT JOIN:
与 JOIN 不同,APPLY 允许您在内部查询中引用 u.id。
Use OUTER APPLY instead of LEFT JOIN:
Unlike JOIN, APPLY allows you to reference the u.id inside the inner query.
调试此类情况的关键是单独运行子查询/内联视图以查看输出是什么:
运行该视图,您将看到
profile_id
值与不匹配
值,这可以解释为什么任何u162231993
的 >u.idmbg
引用都会返回null
(感谢左连接;如果它是内部连接,你将不会得到任何东西)。您已经使用
TOP
将自己编码到了角落,因为现在如果您想为其他用户运行查询,则必须调整查询。更好的方法是:这样,您可以更改
where
子句中的id
值来检查系统中任何用户的记录。The key to debugging situations like these is to run the subquery/inline view on its' own to see what the output is:
Running that, you would see that the
profile_id
value didn't match theu.id
value ofu162231993
, which would explain why anymbg
references would returnnull
(thanks to the left join; you wouldn't get anything if it were an inner join).You've coded yourself into a corner using
TOP
, because now you have to tweak the query if you want to run it for other users. A better approach would be:With that, you can change the
id
value in thewhere
clause to check records for any user in the system.因为有序子查询中的
TOP 1
没有profile_id = 'u162231993'
删除
where u.id = 'u162231993'
并查看结果。单独运行子查询以了解发生了什么。
Because the
TOP 1
from the ordered sub-query does not haveprofile_id = 'u162231993'
Remove
where u.id = 'u162231993'
and see results then.Run the sub-query separately to understand what's going on.
Damir 是正确的,
您的子查询需要确保 dps_user.id 等于 um.profile_id,否则它将抓取顶行,该行可能但可能不等于您的 'u162231993' id
您的查询应如下所示:
Damir is correct,
Your subquery needs to ensure that dps_user.id equals um.profile_id, otherwise it will grab the top row which might, but probably not equal your id of 'u162231993'
Your query should look like this: