Biorąc pod uwagę poniższe zapytanie, może istnieć wiele wierszy w dps_markers z tym samym kluczem znacznika, ale chcemy połączyć tylko z pierwszym. Jeśli wezmę to zapytanie i usunę górną 1 i ORDER BY, otrzymam wartość mbg.marker_value, ale działam tak, jak jest, zawsze zwraca wartość 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'
sql-server
outer-join
dstarh
źródło
źródło
Kluczem do debugowania takich sytuacji jest samodzielne uruchomienie podzapytania / widoku wbudowanego, aby zobaczyć, jaki jest wynik:
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
Po uruchomieniu tego zobaczysz, że
profile_id
wartość nie jest zgodna zu.id
wartościąu162231993
, co wyjaśniałoby, dlaczego jakiekolwiekmbg
referencje wróciłybynull
(dzięki lewemu złączeniu; nie dostałbyś niczego, gdyby było to złączenie wewnętrzne).Zakodowałeś się w kącie za pomocą
TOP
, ponieważ teraz musisz dostosować zapytanie, jeśli chcesz uruchomić je dla innych użytkowników. Lepszym podejściem byłoby: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'
Dzięki temu możesz zmienić
id
wartość wwhere
klauzuli, aby sprawdzić rekordy dla dowolnego użytkownika w systemie.źródło
Ponieważ
TOP 1
z uporządkowanego zapytania podrzędnego nie ma wtedy opcjiprofile_id = 'u162231993'
Usuńwhere u.id = 'u162231993'
i zobacz wyniki.Uruchom zapytanie podrzędne osobno, aby zrozumieć, co się dzieje.
źródło
Damir ma rację,
Twoje podzapytanie musi zapewnić, że dps_user.id jest równe um.profile_id, w przeciwnym razie przejdzie do górnego wiersza, który może, ale prawdopodobnie nie będzie równy Twojemu identyfikatorowi 'u162231993'
Twoje zapytanie powinno wyglądać następująco:
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'
źródło
WHERE um.profile_id = 'u162231993'
w zapytaniu podrzędnym iWHERE mbg.marker_value IS NOT NULL
na zewnątrz.@SearchFor = 'u162231993'
a następnie użyj jej wWHERE
lub opublikuj niektóre struktury danych i tabel, aby inne osoby mogły pomóc i wypróbować.