以下のクエリでは、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'
LEFT JOINの代わりにOUTER APPLYを使用します。
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
の値がu.id
のu162231993
の値と一致しなかったことがわかります。これにより、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'
これにより、id
句のwhere
値を変更して、システム内のユーザーのレコードをチェックできます。
順序付けられたサブクエリのTOP 1
にはprofile_id = 'u162231993'
がないため、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'