排名前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' 

使用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。

debugging像这样的情况的关键是运行在其自己的子查询/内联视图来查看输出是什么:

  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值与u.id值不匹配,这就解释了为什么任何mbg引用都会返回null (感谢左连接;如果是内连接,你不会得到任何东西join)。

您已经使用TOP自己编码到了一个angular落,因为现在如果要为其他用户运行查询,则必须调整该查询。 更好的方法是:

  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值来检查系统中任何用户的logging。

因为来自有序子查询的TOP 1没有profile_id = 'u162231993'删除where u.id = 'u162231993' ,然后查看结果。

分别运行子查询以了解发生了什么。

达米尔是正确的,

你的子查询需要确保dps_user.id等于um.profile_id,否则它将抓住最上面一行,但可能不等于你的“u162231993”

你的查询应该是这样的:

 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'