2012-09-24 11 views
6

Aktualizacja u dołu.W wyniku połączenia OUTER JOIN brakuje wierszy, brak klauzuli WHERE (znaleziono obejście)

Próbuję wykonać sprzężenie zewnętrzne, które dla każdego rekordu zwraca go i wszystkie pozostałe rekordy występujące później, lub NULL, jeśli jest to najnowszy rekord. To jest mój kod SQL:

SELECT A.[CR#], A.REGIS_STATUSDATE, B.REGIS_STATUSDATE 
FROM CR_ADMIN_REGIS_STATUS A LEFT OUTER JOIN CR_ADMIN_REGIS_STATUS B 
ON A.[CR#]=B.[CR#] AND A.REGIS_STATUSDATE < B.REGIS_STATUSDATE 

Mój problem jest to, że gdy na danym [Cr #], A.REGIS_STATUSDATE jest maksymalna (a więc B.REGIS_STATUSDATE nie może być większa niż to), że wiersz nie jest uwzględniony w moim wyniku.

Na przykład, jeśli CR_ADMIN_REGIS_STATUS wygląda następująco:

CR# REGIS_STATUSDATE 
1  5/1/12 
1  5/2/12 
1  5/3/12 
2  5/1/12 
2  5/2/12 

Spodziewam się, że wynik mojego zapytania być

CR# A.REGIS_STATUSDATE B.REGIS_STATUSDATE 
1  5/1/12    5/2/12 
1  5/1/12    5/3/12 
1  5/2/12    5/3/12 
1  5/3/12    NULL 
2  5/1/12    5/2/12 
2  5/2/12    NULL 

Zamiast uzyskać to:

CR# A.REGIS_STATUSDATE B.REGIS_STATUSDATE 
1  5/1/12    5/2/12 
1  5/1/12    5/3/12 
1  5/2/12    5/3/12 
2  5/1/12    5/2/12 

Zważywszy, że moje zapytanie to LEFT OUTER JOIN i nie mam klauzuli WHERE, oczekuję, że wszystkie wiersze z mojego oryginalnego stołu będą w wyniku, ale tak nie jest. Czego tu mi brakuje?

Edit: To jest w programie Access 2007

Aktualizacja: postanowiłem zobaczyć, co by się stało, gdybym kopiowane sekcje stołu CR_ADMIN_REGIS_STATUS w osobnej tabeli i prowadził moje zapytanie przeciwko temu. Nawet gdy tylko od razu skopiowałem całą tabelę do nowej (ręcznie), zapytanie zadziałało! Było tak tylko w przypadku, gdy faktycznie kopiowanie i wklejanie, gdybym WYBIERAŁ * DO INNEJ tabeli, problem trwałby.
W końcu odkryłem, że jeśli będę prowadził kwerendę przeciwko

SELECT * 
FROM CR_ADMIN_REGIS_STATUS 
UNION ALL SELECT TOP 1 * 
FROM CR_ADMIN_REGIS_STATUS; 

zamiast samego CR_ADMIN_REGIS_STATUS moje zapytanie zwróciło pożądanego rezultatu. Dziwne. Miałem podobne zapytanie do podobnej tabeli, która działała od samego początku, więc wydaje się, że była to kwestia ograniczona do tej tabeli.

+1

Która DBMS używasz? Dostęp? –

+0

Cóż, to sprawiło, że podrapałem się w głowę. –

+0

W MS Access 2010 z zapytaniem otrzymuję oczekiwany wynik. – Fionnuala

Odpowiedz

1

Nie brakuje niczego. Jeśli tak się stanie, jest to błąd.

Silnik używany przez MS-Access ma kilka błędów. Widziałem podobne, nieodpowiednie zachowanie w połączeniach, które miały "złożone" warunki. Zobacz inne pytanie, w którym program Access daje błędne wyniki: Why does my left join in Access have fewer rows than the left table?

Możesz wypróbować zapytanie z identycznymi danymi w SQL-Server, Oracle, Postgres, a nawet MySQL, a otrzymasz poprawne, oczekiwane wyniki.


Jako obejście, można spróbować przepisanie zapytania z UNION, ale nigdy nie można mieć pewności co do poprawności:

SELECT A.[CR#], A.REGIS_STATUSDATE, B.REGIS_STATUSDATE 
FROM CR_ADMIN_REGIS_STATUS A 
    INNER JOIN CR_ADMIN_REGIS_STATUS B 
    ON A.[CR#]=B.[CR#] 
    AND A.REGIS_STATUSDATE < B.REGIS_STATUSDATE 

UNION ALL 

SELECT A.[CR#], A.REGIS_STATUSDATE, NULL 
FROM CR_ADMIN_REGIS_STATUS A 
WHERE NOT EXISTS 
     (SELECT * 
     FROM CR_ADMIN_REGIS_STATUS B 
     WHERE A.[CR#]=B.[CR#] 
      AND A.REGIS_STATUSDATE < B.REGIS_STATUSDATE 
    ) ; 
+0

Otrzymuję oczekiwany wynik w MS Access. – Fionnuala

+0

Dziękuję za szybką odpowiedź, równie rozczarowującą, jak usłyszeniem o tym błędzie. Spróbuję Twojego obejścia. – msender

+0

@Remou: Kiedy odpowiedziałem na to inne pytanie, wykonałem kilka testów, z 2 tabelami i bardzo małymi rzędami po 2 lub 3. Kwerendy, które miały wartość "ON a.id = b.id OR a.x IS NULL" lub podobne, dały bardzo dziwne wyniki. –