SQL सर्वर में पंक्ति ऑफ़सेट


133

वहाँ किसी भी तरह से SQL सर्वर परिणाम प्राप्त करने के लिए एक ऑफसेट पर शुरू हो रहा है? उदाहरण के लिए, किसी अन्य प्रकार के SQL डेटाबेस में, यह करना संभव है:

SELECT * FROM MyTable OFFSET 50 LIMIT 25

परिणाम प्राप्त करने के लिए 51-75। यह निर्माण SQL सर्वर में मौजूद नहीं है।

मैं उन सभी पंक्तियों को लोड किए बिना कैसे पूरा कर सकता हूं जिनकी मुझे परवाह नहीं है? धन्यवाद!


आप ऑफ़सेट का उपयोग कर सकते हैं और अगला विवरण प्राप्त कर सकते हैं। youtu.be/EqHkAiiBwPc
अमरेश कुमार सिंह

जवाबों:


152

मैं उपयोग करने से बचूंगा SELECT *। उन स्तंभों को निर्दिष्ट करें जिन्हें आप वास्तव में चाहते हैं, भले ही यह उन सभी में से हो।

SQL सर्वर 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 सर्वर 2000

SQL Server 2000 में बड़े परिणाम सेट के माध्यम से कुशलतापूर्वक पेजिंग

बड़े परिणाम सेट के माध्यम से पेजिंग के लिए एक अधिक कुशल विधि


6
यदि आप सभी कॉलमों का चयन कर रहे हैं, तब भी आप SELECT से बचने का सुझाव क्यों देते हैं?
एडम नेस

12
मुझे यकीन है कि उसने "*" का उपयोग किया था क्योंकि यह टाइप करने के लिए सरल था और "col1, col2, ... colN" से बेहतर बिंदु पर पहुंच गया
gillonba

9
SELECT *इसका उपयोग करने के लिए क्यों नहीं, का अर्थ है कि यदि तालिका की संरचना बदलती है, तो आपकी क्वेरी अभी भी चलती है, लेकिन विभिन्न परिणाम देती है। यदि कोई स्तंभ जोड़ा जाता है, तो यह उपयोगी हो सकता है (हालांकि आपको अभी भी कहीं नाम से इसका उपयोग करने के लिए मिला है); यदि कोई कॉलम हटा दिया जाता है या उसका नाम बदल दिया जाता है, तो आपके एसक्यूएल के लिए यह बेहतर है कि कोड को देखने के बजाय कोड को विचित्र रूप से व्यवहार करना बंद कर दें, क्योंकि एक चर असंवैधानिक है।
IMSoP

5
तालिका और कटौती के सभी डेटा का चयन करें? अगर 5000000000 पंक्तियाँ हैं? प्रत्येक क्वेरी के लिए 5000000000 पंक्तियों का चयन करें और काटें? सीपीयू और सर्वर की मेमोरी के लिए इसकी नहीं।
ई-सूचना128

3
कृपया ध्यान दें कि 2012+ ने इसे बेहतर तरीके से लागू किया है। + मार्टिन स्मिथ द्वारा उत्तर देखें
मध्याह्न

100

यदि आप क्रम में सभी पृष्ठों को संसाधित कर रहे हैं, तो बस पिछले पृष्ठ पर देखे गए अंतिम कुंजी मान को याद रखना और उपयोग TOP (25) ... WHERE Key > @last_key ORDER BY Keyकरना सबसे अच्छा प्रदर्शन तरीका हो सकता है यदि उपयुक्त अनुक्रमणिका इसे कुशलता से प्राप्त करने की अनुमति देने के लिए मौजूद हैं - या एपीआई कर्सर अगर वे नहीं करते हैं ।

एक मध्यस्थ पृष्ठ का चयन करने के लिए SQL Server 2005 - 2008 R2 के लिए सबसे अच्छा समाधान शायद ROW_NUMBERऔर हैBETWEEN

SQL सर्वर 2012+ के लिए आप इस आवश्यकता के लिए बढ़ी हुई ORDER BY क्लॉज का उपयोग कर सकते हैं ।

SELECT  *
FROM     MyTable 
ORDER BY OrderingColumn ASC 
OFFSET  50 ROWS 
FETCH NEXT 25 ROWS ONLY 

हालांकि यह देखा जाना बाकी है कि यह विकल्प कितना अच्छा प्रदर्शन करेगा


2
यह अब SQL सर्वर कॉम्पेक्ट 4.0 में उपलब्ध है -> msdn.microsoft.com/en-us/library/gg699618(v=sql.110).aspx
Bart Verkoeijen

13
यह समय है जब उन्होंने इसे 14 दिसंबर को tSQL
JohnFx

3
केवल Sql सर्वर 2012 के लिए :(
ई-जानकारी128

22

यह एक तरीका है (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

और यह एक और तरीका है (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

बस पहले एक को स्पष्ट करने के लिए ... (@pageSize) वास्तविक मूल्य के लिए यहां एक प्लेसहोल्डर है। आपको विशेष रूप से 'TOP 25' करना होगा; SQL सर्वर 2000 किसी शीर्ष खंड में चर का समर्थन नहीं करता है। यह इसे गतिशील एसक्यूएल को शामिल करने वाला दर्द बनाता है।
कोवान

5
SQL2000 के लिए यह समाधान परिणाम सेट में अंतिम पृष्ठ के लिए काम नहीं करता है, जब तक कि पंक्तियों की कुल संख्या पृष्ठ के आकार का एक से अधिक न हो जाए।
बिल कार्विन

10

आप ROW_NUMBER()जो चाहें प्राप्त करने के लिए फ़ंक्शन का उपयोग कर सकते हैं:

SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY id) RowNr, id FROM tbl) t
WHERE RowNr BETWEEN 10 AND 20

7

नहीं है OFFSET .. FETCHएसक्यूएल सर्वर 2012 में, लेकिन आप एक निर्दिष्ट करना होगा ORDER BYस्तंभ।

यदि आपके पास वास्तव में कोई स्पष्ट कॉलम नहीं है जिसे आप एक ORDER BYकॉलम के रूप में पारित कर सकते हैं (जैसा कि दूसरों ने सुझाव दिया है), तो आप इस ट्रिक का उपयोग कर सकते हैं:

SELECT * FROM MyTable 
ORDER BY @@VERSION 
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY

... या

SELECT * FROM MyTable 
ORDER BY (SELECT 0)
OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY

हम इसका उपयोग jOOQ में कर रहे हैं जब उपयोगकर्ता स्पष्ट रूप से एक आदेश निर्दिष्ट नहीं करते हैं। यह तब किसी भी अतिरिक्त लागत के बिना बहुत यादृच्छिक क्रम का उत्पादन करेगा।


6

अधिक और बड़े डेटा कॉलम वाली तालिकाओं के लिए, मैं पसंद करता हूं:

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.

बीएलओबी जैसे बड़े डेटा वाले तालिकाओं पर इसका बेहतर प्रदर्शन है, क्योंकि ROW_NUMBER फ़ंक्शन को केवल एक कॉलम के माध्यम से देखना है, और सभी स्तंभों के साथ केवल मिलान पंक्तियों को लौटाया गया है।


5

पेजिनेटर के लिए मेरा चयन देखें

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

यह पृष्ठन को हल करता है;)


3
SELECT TOP 75 * FROM MyTable
EXCEPT 
SELECT TOP 50 * FROM MyTable

प्रदर्शन समझदारी इष्टतम नहीं लगती क्योंकि क्वेरी तब अनावश्यक रूप से दो बार निष्पादित की जाती है। विशेष रूप से जब उपयोगकर्ता उच्चतर पृष्ठों पर जाता है, तो पंक्तियों को छोड़ने के लिए क्वेरी यानी EXCEPT के नीचे का हिस्सा अधिक लंबा और लंबा होगा।
वैनवैल

2

आपके संस्करण के आधार पर आप इसे सीधे नहीं कर सकते हैं, लेकिन आप ऐसा कुछ हैक कर सकते हैं

select top 25 *
from ( 
  select top 75 *
  from   table 
  order by field asc
) a 
order by field desc 

जहाँ 'फ़ील्ड' कुंजी है।


4
SQL2000 के लिए यह समाधान परिणाम सेट में अंतिम पृष्ठ के लिए काम नहीं करता है, जब तक कि पंक्तियों की कुल संख्या पृष्ठ के आकार का एक से अधिक न हो जाए।
बिल कार्विन

2

निम्नलिखित SQL सर्वर 2012 में पहले 50 रिकॉर्ड कार्यों को छोड़कर 25 रिकॉर्ड प्रदर्शित करेगा।

SELECT * FROM MyTable ORDER BY ID OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY;

आप अपनी आवश्यकता के अनुसार आईडी बदल सकते हैं


Pls इसे भी जोड़ें, यह SQL SERVER 2012 में संभव है
उस्मान यूनुस

2

ROW_NUMBER() OVER (ORDER BY)कथन का उपयोग करते समय आपको सावधान रहना चाहिए क्योंकि प्रदर्शन काफी खराब है। उसी के साथ कॉमन टेबल एक्सप्रेशंस का उपयोग ROW_NUMBER()करने के लिए भी यही होता है। मैं निम्नलिखित स्निपेट का उपयोग कर रहा हूं जो पृष्ठ संख्या प्रदान करने के लिए एक पहचान के साथ टेबल चर का उपयोग करने की तुलना में थोड़ा तेज साबित हुआ है।

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

यह 11 पंक्तियों को लौटाएगा, 10. नहीं
हारून बर्ट्रेंड

1

मैं इस तकनीक का उपयोग पेजिंग के लिए करता हूं। मैं सभी पंक्तियों को नहीं लाता हूं। उदाहरण के लिए, यदि मेरे पृष्ठ को शीर्ष 100 पंक्तियों को प्रदर्शित करने की आवश्यकता है तो मैं केवल 100 को जहां खंड के साथ लाऊं। SQL के आउटपुट में एक अद्वितीय कुंजी होनी चाहिए।

तालिका में निम्नलिखित हैं:

ID, KeyId, Rank

एक ही रैंक एक से अधिक KeyId के लिए असाइन किया जाएगा।

एसक्यूएल है select top 2 * from Table1 where Rank >= @Rank and ID > @Id

पहली बार मैं दोनों के लिए 0 पास हूं। दूसरी बार पास 1 & 14. 3 टाइम पास 2 और 6 ...।

10 वीं रिकॉर्ड रैंक और आईडी का मान अगले पास किया गया है

11  21  1
14  22  1
7   11  1
6   19  2
12  31  2
13  18  2

इससे सिस्टम पर कम से कम तनाव होगा


1

SqlServer2005 में आप निम्नलिखित कार्य कर सकते हैं:

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) 

यह नहीं होना चाहिए @Offset + @Limit - 1? यदि @Litit 10 है तो यह 11 पंक्तियों को लौटा देगा।
एरॉन बर्ट्रैंड

1

रिकॉर्ड बनाने के लिए समय बर्बाद किए बिना इसे करने का सबसे अच्छा तरीका है:

select 0 as tmp,Column1 from Table1 Order by tmp OFFSET 5000000 ROWS FETCH NEXT 50 ROWS ONLY

यह एक सेकंड से भी कम समय लेता है!
बड़ी मेज के लिए सबसे अच्छा समाधान।


0

मैं अब कुछ समय के लिए (सामान्य प्रश्नों के लिए) इस उत्तर की खोज कर रहा था और इसे SQL सर्वर 2000+ पर ROWCOUNT और कर्सर का उपयोग करके और बिना TOP या किसी भी अस्थायी तालिका का उपयोग करने का एक और तरीका पता चला।

उपयोग करने से SET ROWCOUNT [OFFSET+LIMIT]आप परिणामों को सीमित कर सकते हैं, और कर्सर के साथ, अपनी इच्छित पंक्ति पर सीधे जा सकते हैं, फिर अंत तक 'लूप' कर सकते हैं।

तो आपकी क्वेरी इस तरह होगी:

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

जब आप तालिका के अंत की ओर बढ़ते हैं, तो मैं इसके प्रदर्शन को देखने से घृणा करूंगा ...
हारून बर्ट्रेंड

0

SQL Server 2012 (11.x) और बाद में और Azure SQL डेटाबेस के साथ, आप "fetch_row_count_expression" भी कर सकते हैं, इसके साथ आप ORDER BY खंड भी कर सकते हैं।

USE AdventureWorks2012;  
GO  
-- Specifying variables for OFFSET and FETCH values    
DECLARE @skip int = 0  , @take int = 8;  
SELECT DepartmentID, Name, GroupName  
FROM HumanResources.Department  
ORDER BY DepartmentID ASC   
    OFFSET @skip ROWS   
    FETCH NEXT @take ROWS ONLY; 

https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-ver15

नोट OFFSET क्वेरी अभिव्यक्ति से पंक्तियों को वापस करने से पहले छोड़ने के लिए पंक्तियों की संख्या निर्दिष्ट करता है । यह शुरुआती पंक्ति संख्या नहीं है। इसलिए, पहला रिकॉर्ड शामिल करने के लिए इसे 0 होना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.