2010-05-28 14 views
12

Używam programu SQL Server 2005 i próbuję osiągnąć coś takiego: Chcę uzyskać pierwsze x wierszy i ostatnie x wiersze w tym samym oświadczeniu select.Wybierz górny i dolny wiersz

SELECT TOP(5) BOTTOM(5) 

Oczywiście BOTTOM nie istnieje, więc trzeba innego rozwiązania. Uważam, że istnieje proste i eleganckie rozwiązanie, którego nie otrzymuję. Wykonywanie wyboru ponownie za pomocą GROUP BY DESC nie jest opcją.

Odpowiedz

22

Korzystanie z unii jest jedyną rzeczą, którą mogę myśleć, aby osiągnąć ten cel

select * from (select top(5) * from logins order by USERNAME ASC) a 
union 
select * from (select top(5) * from logins order by USERNAME DESC) b 
+0

Istnieje również sposób użycia rownumber . I powinieneś być na samej górze 2. – hgulyan

+1

@hgulyan: TOP (x) jest preferowaną metodą - działa również z UPDATE i DELETE, a także pozwala ci napisać 'TOP (20%)' lub 'TOP (@limit)' i tak na –

+0

Tego nie wiedziałem. Dzięki za informację. – hgulyan

8

Sprawdź link

SQL SERVER – How to Retrieve TOP and BOTTOM Rows Together using T-SQL

Próbowałaś do korzystania RowNumber?

SELECT * 
FROM 
(SELECT *, ROW_NUMBER() OVER (Order BY columnName) as TopFive 
    ,ROW_NUMBER() OVER (Order BY columnName Desc) as BottomFive 
    FROM Table 
) 
WHERE TopFive <=5 or BottomFive <=5 

http://www.sqlservercurry.com/2009/02/select-top-n-and-bottom-n-rows-using.html

+1

ten kod nie zadziała. 'Top5' i' Bottom5' nie mogą być przywoływane w ten sposób, otrzymujesz 'Msg 207, Level 16, State 1, Line 4 Niepoprawna nazwa kolumny 'TopFive' ...' Jeśli wstawisz 'ROW_NUMBER ...'w TYM, GDZIE dostaniesz' Msg 4108, Level 15, State 1, Line 1 Windowed funkcje mogą pojawiać się tylko w klauzulach SELECT lub ORDER BY. Musisz opakować SELECT i FROM w wyprowadzoną tabelę i pociągnąć WHERE do zewnętrzne zapytanie, aby to zadziałało, tak jak [@Paul zrobił w drugiej metodzie w swojej odpowiedzi] (http://stackoverflow.com/questions/2927475/sql-server-select-top-and-bottom-rows/2927515#2927515). –

+0

Edytowane zapytanie. To był duży błąd. – hgulyan

+1

To będzie działać jak pies bez nóg. Użyj UNIONA – gbn

1

Wtedy jesteś out - robi select znowu jest jedyną opcją, chyba że chcesz ciągnąć w kompletnym zestawie wyników, a potem wyrzucać wszystko pomiędzy.

Dowolny sql, o którym myślę, jest taki sam - na dole musisz najpierw wiedzieć, ile masz elementów (zmaterializuj wszystko lub użyj liczby (*)) lub odwróć porządek sortowania.

Przepraszam, jeśli to nie pasuje, ale na końcu ... rzeczywistość nie obchodzi, i nie widzę innego sposobu, aby to zrobić.

1

chyba trzeba to zrobić za pomocą podzapytania tylko

select * from table where id in ( 
      (SELECT id ORDER BY columnName LIMIT 5) OR 
      (SELECT id ORDER BY columnName DESC LIMIT 5) 
) 


select * from table where id in ( 
      (SELECT TOP(5) id ORDER BY columnName) OR 
      (SELECT TOP(5) id ORDER BY columnName DESC) 
) 

ZREDAGOWANE

select * from table where id in ( 
      (SELECT TOP 5 id ORDER BY columnName) OR 
      (SELECT TOP 5 id ORDER BY columnName DESC) 
) 
+0

To jest serwer sql, więc zamiast LIMIT, musisz użyć TOP – hgulyan

+0

oohhhhhhhhh thanx @hgulyan i edytować to może pomóc :) – Salil

+0

Msg 156, Poziom 15, Stan 1, Linia 3 Niepoprawna składnia w pobliżu słowa kluczowego "ZAMÓWIENIE". –

3

Czy jest możliwe, abyś użył związku?

E.g.

select top 5 ... order by {specify columns asc} 
union 
select top 5 ... order by {specify columns desc} 
+1

Jeśli umieścisz kod, * proszę * zaznaczyć linie i kliknąć przycisk "kod" (101 010) na pasku narzędzi edytora! –

7

Myślę, że dwie główne opcje:

SELECT TOP 5 ... 
FROM ... 
ORDER BY ... ASC 

UNION 

SELECT TOP 5 ... 
FROM ... 
ORDER BY ... DESC 

Albo, jeśli wiesz, jak wiele elementów są w tabeli:

SELECT ... 
FROM (
    SELECT ..., ROW_NUMBER() OVER (ORDER BY ... ASC) AS intRow 
    FROM ... 
) AS T 
WHERE intRow BETWEEN 1 AND 5 OR intRow BETWEEN @Number - 5 AND @Number 
2

Nie prawdziwa różnica między tym i związek, o którym jestem świadomy, ale technicznie jest to pojedyncze zapytanie.

select t.* 
from table t 
where t.id in (select top 5 t2.id from table t2 order by MyColumn) 
    or 
    t.id in (select top 5 t2.id from table t2 order by MyColumn desc); 
0

Musiałem zrobić to ostatnio dla bardzo dużej procedury przechowywanej; Jeśli zapytanie jest dość duży, a chcesz zminimalizować ilość zapytań mogły zadeklarować @tempTable, wstawić do tego @tempTable następnie kwerendy z tego @tempTable,

DECLARE @tempTable TABLE (columns..) 
INSERT INTO @tempTable 
VALUES (SELECT.. your query here ..) 

SELECT TOP(5) columns FROM @tempTable ORDER BY column ASC -- returns first to last 
SELECT TOP(5) columns FROM @tempTable ORDER BY column DESC -- returns last to first 
Powiązane problemy