2012-11-04 15 views
7

Mam następujące kwerendy chcę ognia:Zapytanie SQL - połączyć DISTINCT i TOP?

SELECT DISTINCT TOP(5) fp.PostId FROM dbForumPosts fp 
LEFT JOIN dbForumEntry fe ON fp.PostId = fe.PostId 
Order by fe.Datemade DESC 

Jednak, kiedy ogień go, pojawia się błąd:

Msg 145, Level 15, State 1, Line 1 
ORDER BY items must appear in the select list if SELECT DISTINCT is specified. 

Próbowałem zmienić zapytanie, dlatego stosowany GROUP BY zamiast tego, ale potem mam następujący problem:

Msg 8127, Level 16, State 1, Line 4 
Column "dbForumEntry.Datemade" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause. 

co chcę:

Pomyśl o tym jako o forum. Istnieją posty (dbForumPosts) i wpisy (dbForumEntry). Istnieje 0-wiele wpisów pr post.

Czego chcę, to otrzymywać posty z najnowszą działalnością (posty z najnowszymi aktualizacjami w).

+0

Z jakiego DBMS korzystasz? –

+0

SQL Server 2008 R2 (MSSQL) –

+0

Czy może być więcej niż jedna 'Datemade' na' PostId'? Jeśli tak, który z nich użyć do celów zamówienia? –

Odpowiedz

5

Można znaleźć najnowsze Datemade na PostId z row_number. Następnie można wyszukać ostatnich 5 stanowisk:

select top 5 PostId 
from (
     select PostId 
     ,  Datemade 
     ,  row_number() over (partition by PostId 
        order by Datemade) as rn 
     from dbForumEntry 
     ) SubQueryAlias 
where rn = 1 -- Most recent row per PostId 
order by 
     Datemade desc 

Alternatywnie, można osiągnąć to samo z group by podzapytaniu:

select top 5 PostId 
from (
     select PostId 
     ,  max(Datemade) as LastDate 
     from dbForumEntry 
     group by 
       PostId 
     ) SubQueryAlias 
order by 
     LastDate desc 

Jeśli dbForumEntry ma kolumnę ID (słownie ForumEntryId), kwerendy tak jak to może działać lepiej. Baza danych może uruchomić to bez kompilowania row_number lub max(Datemade) dla całej tabeli.

select top 5 PostId 
from dbForumPosts fp 
where not exists -- No later entry for the same post exists 
     (
     select * 
     from dbForumPosts fp2 
     where fp2.PostId = fp.PostId 
       and fp2.ForumEntryId > fp.ForumEntryId 
     ) 
order by 
     Datemade desc 
+0

Wielkie dzięki - to naprawdę pomogło :-)! Dzięki. –