Przesunięcie wiersza w SQL Server
Czy Jest jakiś sposób w SQL Server, aby uzyskać wyniki zaczynające się od danego offsetu? Na przykład w innym typie bazy danych SQL można wykonać:
SELECT * FROM MyTable OFFSET 50 LIMIT 25
Aby uzyskać wyniki 51-75. Ta konstrukcja nie wydaje się istnieć w SQL Server.
Jak mogę to osiągnąć bez ładowania wszystkich wierszy, na których mi nie zależy? Dzięki!
15 answers
Unikałbym używania SELECT *
. Określ kolumny, które chcesz, nawet jeśli mogą to być wszystkie z nich.
SQL Server 2005+
SELECT col1, col2
FROM (
SELECT col1, col2, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum
FROM MyTable
) AS MyDerivedTable
WHERE MyDerivedTable.RowNum BETWEEN @startRow AND @endRow
SQL Server 2000
Wydajne przeglądanie dużych zestawów wyników w SQL Server 2000
Bardziej efektywna metoda stronicowania dużych zbiorów wyników
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 04:45:49
Jeśli będziesz przetwarzać wszystkie strony w kolejności, to po prostu zapamiętaj ostatnią wartość klucza widoczną na poprzedniej stronie i użyj TOP (25) ... WHERE Key > @last_key ORDER BY Key
może być najlepiej działającą metodą, jeśli istnieją odpowiednie indeksy, które pozwalają na efektywne wyświetlanie tej strony - lub kursor API , Jeśli nie.
Do wyboru strony arbiter najlepszym rozwiązaniem dla SQL Server 2005-2008 R2 jest prawdopodobnie ROW_NUMBER
i BETWEEN
Dla SQL Server 2012+ możesz użyć rozszerzonej klauzuli ORDER BY do tego potrzeba.
SELECT *
FROM MyTable
ORDER BY OrderingColumn ASC
OFFSET 50 ROWS
FETCH NEXT 25 ROWS ONLY
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 12:42:40
This is one way (SQL2000)
SELECT * FROM
(
SELECT TOP (@pageSize) * FROM
(
SELECT TOP (@pageNumber * @pageSize) *
FROM tableName
ORDER BY columnName ASC
) AS t1
ORDER BY columnName DESC
) AS t2
ORDER BY columnName ASC
I to jest inny sposób (SQL 2005)
;WITH results AS (
SELECT
rowNo = ROW_NUMBER() OVER( ORDER BY columnName ASC )
, *
FROM tableName
)
SELECT *
FROM results
WHERE rowNo between (@pageNumber-1)*@pageSize+1 and @pageNumber*@pageSize
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-10 03:43:47
Możesz użyć funkcji ROW_NUMBER()
, Aby uzyskać to, co chcesz:
SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY id) RowNr, id FROM tbl) t
WHERE RowNr BETWEEN 10 AND 20
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-24 07:07:38
Dla tabel z większą ilością i dużymi kolumnami danych preferuję:
SELECT
tablename.col1,
tablename.col2,
tablename.col3,
...
FROM
(
(
SELECT
col1
FROM
(
SELECT col1, ROW_NUMBER() OVER (ORDER BY col1 ASC) AS RowNum
FROM tablename
WHERE ([CONDITION])
)
AS T1 WHERE T1.RowNum BETWEEN [OFFSET] AND [OFFSET + LIMIT]
)
AS T2 INNER JOIN tablename ON T2.col1=tablename.col1
);
-
[CONDITION] can contain any WHERE clause for searching.
[OFFSET] specifies the start,
[LIMIT] the maximum results.
Ma znacznie lepszą wydajność w tabelach z dużymi danymi, takimi jak Blob, ponieważ funkcja ROW_NUMBER musi przeglądać tylko jedną kolumnę, a tylko pasujące wiersze są zwracane ze wszystkimi kolumnami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-25 15:37:59
W SQL Server 2012 jest OFFSET .. FETCH
, ale musisz podać kolumnę ORDER BY
.
Jeśli naprawdę nie masz żadnej wyraźnej kolumny, którą mógłbyś przekazać jako ORDER BY
kolumna (jak sugerowali inni), możesz użyć tej sztuczki:
SELECT * FROM MyTable
ORDER BY @@VERSION
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY
... lub
SELECT * FROM MyTable
ORDER BY (SELECT 0)
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY
Używamy go w jOOQ, gdy użytkownicy nie określają wprost kolejności. Spowoduje to wtedy dość losowe zamawianie bez żadnych dodatkowych kosztów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-13 06:39:01
Zobacz mój wybór paginatora
SELECT TOP @limit * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY colunx ASC) offset, * FROM (
-- YOU SELECT HERE
SELECT * FROM mytable
) myquery
) paginator
WHERE offset > @offset
To rozwiązuje paginację;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-23 18:34:44
SELECT TOP 75 * FROM MyTable
EXCEPT
SELECT TOP 50 * FROM MyTable
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-21 08:05:32
W zależności od wersji nie można tego zrobić bezpośrednio, ale można zrobić coś hacky jak
select top 25 *
from (
select top 75 *
from table
order by field asc
) a
order by field desc
Gdzie' pole ' jest kluczem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-09 16:20:56
Powinieneś być ostrożny, gdy używasz instrukcji row_number () OVER (ORDER BY), ponieważ performane jest dość słabe. To samo dotyczy używania zwykłych wyrażeń tabel z funkcją row_number (), co jest jeszcze gorsze. Używam poniższego fragmentu, który okazał się nieco szybszy niż użycie zmiennej tabelkowej z tożsamością, aby podać numer strony.
DECLARE @Offset INT = 120000
DECLARE @Limit INT = 10
DECLARE @ROWCOUNT INT = @Offset+@Limit
SET ROWCOUNT @ROWCOUNT
SELECT * FROM MyTable INTO #ResultSet
WHERE MyTable.Type = 1
SELECT * FROM
(
SELECT *, ROW_NUMBER() OVER(ORDER BY SortConst ASC) As RowNumber FROM
(
SELECT *, 1 As SortConst FROM #ResultSet
) AS ResultSet
) AS Page
WHERE RowNumber BETWEEN @Offset AND @ROWCOUNT
DROP TABLE #ResultSet
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-27 15:10:37
Po wyświetli 25 rekordów z wyłączeniem pierwszych 50 rekordów działających w SQL Server 2012.
SELECT * FROM MyTable ORDER BY ID OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY;
Możesz zastąpić ID jako swoje Wymaganie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-09 09:56:23
Używam tej techniki do paginacji. Nie zbieram wszystkich rzędów. Na przykład, jeśli moja strona musi wyświetlić górne wiersze 100, pobieram tylko 100 z klauzulą where. Wyjście SQL powinno mieć unikalny klucz.
Tabela zawiera:
ID, KeyId, Rank
Ta sama ranga będzie przypisana dla więcej niż jednego KeyId.
SQL to select top 2 * from Table1 where Rank >= @Rank and ID > @Id
Po raz pierwszy zdaję 0 za oba. Drugi raz pass 1 i 14. 3. time pass 2 i 6....
Wartość dziesiątego ranga & ID rekordu jest przekazywane do następnego
11 21 1
14 22 1
7 11 1
6 19 2
12 31 2
13 18 2
To będzie miało najmniejszy nacisk na system
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 21:34:48
W SqlServer2005 możesz wykonać następujące czynności:
DECLARE @Limit INT
DECLARE @Offset INT
SET @Offset = 120000
SET @Limit = 10
SELECT
*
FROM
(
SELECT
row_number()
OVER
(ORDER BY column) AS rownum, column2, column3, .... columnX
FROM
table
) AS A
WHERE
A.rownum BETWEEN (@Offset) AND (@Offset + @Limit-1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-27 18:09:50
Szukałem tej odpowiedzi od jakiegoś czasu (dla ogólnych zapytań) i znalazłem inny sposób na zrobienie tego na SQL Server 2000+ za pomocą ROWCOUNT i kursorów i bez TOP lub żadnej tymczasowej tabeli.
Za pomocą SET ROWCOUNT [OFFSET+LIMIT]
możesz ograniczyć wyniki i za pomocą kursorów przejść bezpośrednio do żądanego wiersza, a następnie zapętlić 'do końca.
Więc twoje zapytanie będzie takie:
SET ROWCOUNT 75 -- (50 + 25)
DECLARE MyCursor SCROLL CURSOR FOR SELECT * FROM pessoas
OPEN MyCursor
FETCH ABSOLUTE 50 FROM MyCursor -- OFFSET
WHILE @@FETCH_STATUS = 0 BEGIN
FETCH next FROM MyCursor
END
CLOSE MyCursor
DEALLOCATE MyCursor
SET ROWCOUNT 0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-13 17:58:02
Najlepszy sposób, aby to zrobić bez marnowania czasu na zamawianie płyt jest taki:
select 0 as tmp,Column1 from Table1 Order by tmp OFFSET 5000000 ROWS FETCH NEXT 50 ROWS ONLY
To zajmuje mniej niż sekundę!najlepsze rozwiązanie dla dużych stołów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-15 13:53:13