SQL सर्वर के लिए LIMIT और OFFSET के बराबर?


172

PostgreSQL में ऐसे कीवर्ड Limitऔर Offsetकीवर्ड हैं जो परिणाम सेट के बहुत आसान पृष्ठांकन की अनुमति देंगे।

SQL सर्वर के लिए बराबर सिंटैक्स क्या है?


Sql सर्वर 2012 के लिए, यह सुविधा आसान तरीके से लागू की गई है। मेरा उत्तर
सोमनाथ मुलुक

इस सवाल को पूछने के लिए धन्यवाद, हमें MySQL से MsSQL में संक्रमण के लिए मजबूर किया जा रहा है :(
tempcke

आप खंड में आर्डर के साथ SQL सर्वर में ऑफ़सेट और अगला स्टेटमेंट प्राप्त कर सकते हैं। इसे आज़माएं youtu.be/EqHkAiiBwPc
अमरेश कुमार सिंह

जवाबों:


139

के बराबर LIMITहै SET ROWCOUNT, लेकिन अगर आप जेनेरिक पेजिनेशन चाहते हैं तो इस तरह से क्वेरी लिखना बेहतर है:

;WITH Results_CTE AS
(
    SELECT
        Col1, Col2, ...,
        ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
    FROM Table
    WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= @Offset
AND RowNum < @Offset + @Limit

यहाँ लाभ ऑफसेट और सीमा का पैरामीटरकरण है यदि आप अपने पेजिंग विकल्पों को बदलने का निर्णय लेते हैं (या उपयोगकर्ता को ऐसा करने की अनुमति देते हैं)।

नोट:@Offset पैरामीटर सामान्य शून्य आधारित अनुक्रमण की तुलना में इस बल्कि के लिए एक आधार अनुक्रमण का उपयोग करना चाहिए।


22
अभी पुराना है। Sql सर्वर 2012 और बाद में OFFSET / FETCH का समर्थन
जोएल

31
@JoelCoehoorn पुराना नहीं है। मुझे सिर्फ SLQ सर्वर 2008 का उपयोग करके प्रोजेक्ट करने का काम सौंपा गया है, जो अतीत में केवल mysql का उपयोग करता था ...
Cthulhu

यह काफी अच्छा है, लेकिन एक छोटे से ajusted करने की आवश्यकता हैWHERE RowNum >= (@Offset + 1)
एरिक Herlitz

5
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified। MSSQL2008 R2।
पॉल

2
@ यदि कोई मेरे Tableपास 200k रिकॉर्ड है, तो वह सबसे पहले लाएगा , फिर सीमा लागू करेगा? क्या यह प्रश्न कुशल है?
जिगर

231

यह सुविधा अब SQL Server 2012 में आसान हो गई है। यह SQL सर्वर 2012 से आगे काम कर रहा है।

SQL सर्वर में 11 से 20 पंक्तियों का चयन करने के लिए ऑफसेट के साथ सीमा:

SELECT email FROM emailTable 
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
  • OFFSET: स्किप की गई पंक्तियों की संख्या
  • NEXT: अगली पंक्तियों की आवश्यक संख्या

संदर्भ: https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017


4
क्या SQL_CALC_FOUND_ROWSइसका उपयोग करते समय कोई समानता है ?
पेटा

1
@Petah @@ Rowcount आपको देगा कि मुझे लगता है
Rob Sedgwick

GOTCHA: आप इसे CTE के भीतर से उपयोग नहीं कर सकते। इसे मुख्य क्वेरी में उपयोग किया जाना है। मैं दी गई पंक्तियों (पेजिनेशन) की मात्रा को सीमित करना चाहता था और फिर 10 या इतनी पंक्तियों के लिए एक महंगी गणना करता था, पंक्तियों को निर्धारित करने के बजाय, महंगी गणना का प्रदर्शन करता हूं, और फिर जो मुझे चाहिए उसे छोड़ / देता है। @ हारूनहट का जवाब एक सीटीई के भीतर पंक्तियों को प्रतिबंधित करने की आवश्यकता वाले लोगों के लिए काम करेगा।
डेरिक डीन

@ सोमनाथ मुलुक यह ऑफ़सेट और भ्रूण 1000000 की ऑफ़सेट के साथ अधिक मात्रा में डेटा उदाहरण के लिए बहुत समय ले रहा है। मैं इससे कैसे निपट सकता हूं।
सरोज श्रेष्ठ

1
@ सरोजश्रेष्ठ: यह ऑफ़सेट और फ़ेच मसला नहीं है। अब आपको अपनी तालिका की वास्तुकला को फिर से देखना चाहिए। तालिकाओं के विभाजन पर विचार करें, आपकी डेटा पंक्ति और यह विभिन्न स्तंभ प्रकार और कुल तालिका आकार है, नियमित रूप से आवश्यक नहीं होने पर कुछ पंक्तियों को संग्रहीत करने पर विचार करें, अपने सर्वर चश्मा की जांच करें।
सोमनाथ मुलुक

23
select top {LIMIT HERE} * from (
      select *, ROW_NUMBER() over (order by {ORDER FIELD}) as r_n_n 
      from {YOUR TABLES} where {OTHER OPTIONAL FILTERS}
) xx where r_n_n >={OFFSET HERE}

एक नोट: यह समाधान केवल SQL Server 2005 या इसके बाद के संस्करण में काम करेगा, क्योंकि यह तब ROW_NUMBER()लागू किया गया था।


मैं थोड़ी देर के लिए इस क्वेरी का उपयोग कर रहा हूं और यह उसके लिए बहुत अच्छा काम करता है। मैं सोच रहा हूँ कि 'xx' क्या दर्शाता है?
उर्लेरी

उप क्वेरी को एक नाम की आवश्यकता होती है। के रूप में मैं इसका इस्तेमाल नहीं कर रहा हूँ बस xx वहाँ रख
jorgeu

2
Xx केवल एक तालिका उपनाम है। यह थोड़ा स्पष्ट हो सकता है अगर आपने कहाAS xx
कंक्रीट गनेट 23

किसी को पता है कि इस क्वेरी पर लेफ्ट जॉइन कैसे करना है?
Drenyl

12

इसे प्राप्त करने के लिए आप कॉमन टेबल एक्सप्रेशन में ROW_NUMBER का उपयोग कर सकते हैं।

;WITH My_CTE AS
(
     SELECT
          col1,
          col2,
          ROW_NUMBER() OVER(ORDER BY col1) AS row_number
     FROM
          My_Table
     WHERE
          <<<whatever>>>
)
SELECT
     col1,
     col2
FROM
     My_CTE
WHERE
     row_number BETWEEN @start_row AND @end_row

4

मेरे लिए OFFSET और FETCH का उपयोग एक साथ धीमा था, इसलिए मैंने TOP और OFFSET के संयोजन का उपयोग इस तरह किया (जो तेज था):

SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

नोट: यदि आप एक ही क्वेरी में एक साथ TOP और OFFSET का उपयोग करते हैं:

SELECT TOP 20 columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS

फिर आपको एक त्रुटि मिलती है, इसलिए TOP और OFFSET का उपयोग करने के लिए आपको इसे एक उप-क्वेरी के साथ अलग करने की आवश्यकता होती है।

और अगर आपको SELECT DISTINCT का उपयोग करना है तो क्वेरी निम्न है:

SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

नोट: DISTINCT के साथ SELECT ROW_NUMBER का उपयोग मेरे काम नहीं आया।


1
मुझे लगता है कि "A TOP को एक ही क्वेरी या OFFSET के रूप में उप-क्वेरी में उपयोग नहीं किया जा सकता है।
माइकलरशटन

आप सही @MichaelRushton हैं, एक ही क्वेरी में या एक ही उप-क्वेरी में उपयोग नहीं किया जा सकता है, तो आपको इसे अलग करने के लिए एक उप-क्वेरी का उपयोग करना होगा। इसलिए यदि आपके पास एसक्यूएल जैसा है SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows, तो आपको इसे बदलना होगा SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1। मैं अपने उत्तर को संपादित करूंगा। धन्यवाद और मुझे मेरी अंग्रेजी बहाना।
सीबसदेव

2

एक और नमूना:

declare @limit int 
declare @offset int 
set @offset = 2;
set @limit = 20;
declare @count int
declare @idxini int 
declare @idxfim int 
select @idxfim = @offset * @limit
select @idxini = @idxfim - (@limit-1);
WITH paging AS
    (
        SELECT 
             ROW_NUMBER() OVER (order by object_id) AS rowid, *
        FROM 
            sys.objects 
    )
select *
    from 
        (select COUNT(1) as rowqtd from paging) qtd, 
            paging 
    where 
        rowid between @idxini and @idxfim
    order by 
        rowid;

15
मैंने आपका एंटी-माइक्रोसॉफ्ट नफरत वाला भाषण हटा दिया। यहाँ पवित्र युद्धों पर चर्चा न करें; बस गैर-व्यक्तिपरक तरीके से प्रश्नों का उत्तर दें और पूछें।
अर्लज़

2

नहीं है यहाँ एसक्यूएल 2011 में इस सुविधा, अपने दुख की बात है कि वे थोड़ा अलग कीवर्ड चुनें "ऑफसेट / प्राप्त करें" लेकिन इसके standart तो ठीक नहीं के बारे में किसी को बताने।


2

हारून के समाधान पर थोड़ा बदलाव करते हुए, मैं आमतौर पर पेज नंबर (@ पेज) और पेज का आकार (@ पेजेज) तय करता हूं। इस तरह से प्रत्येक पृष्ठ पर क्लिक किया गया ईवेंट केवल अनुरोधित पृष्ठ संख्या में एक कॉन्फ़िगर करने योग्य पृष्ठ आकार के साथ भेजता है:

begin
    with My_CTE  as
    (
         SELECT col1,
              ROW_NUMBER() OVER(ORDER BY col1) AS row_number
     FROM
          My_Table
     WHERE
          <<<whatever>>>
    )
    select * from My_CTE
            WHERE RowNum BETWEEN (@PageNum - 1) * (@PageSize + 1) 
                              AND @PageNum * @PageSize

end

2

निकटतम मैं कर सकता है

select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber  and ct <= toNumber

जिसका मुझे अनुमान है select * from [db].[dbo].[table] LIMIT 0, 10


1
select top (@TakeCount) * --FETCH NEXT
from(
    Select  ROW_NUMBER() OVER (order by StartDate) AS rowid,*
    From YourTable
)A
where Rowid>@SkipCount --OFFSET

1
@nombre_row :nombre ligne par page  
@page:numero de la page

//--------------code sql---------------

declare  @page int,@nombre_row int;
    set @page='2';
    set @nombre_row=5;
    SELECT  *
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY etudiant_ID ) AS RowNum, *
      FROM      etudiant

    ) AS RowConstrainedResult
WHERE   RowNum >= ((@page-1)*@nombre_row)+1
    AND RowNum < ((@page)*@nombre_row)+1
ORDER BY RowNum

1

चूंकि किसी ने अभी तक यह कोड प्रदान नहीं किया है:

SELECT TOP @limit f1, f2, f3...
FROM t1
WHERE c1 = v1, c2 > v2...
AND
    t1.id NOT IN
        (SELECT TOP @offset id
         FROM t1
         WHERE c1 = v1, c2 > v2...
         ORDER BY o1, o2...)
ORDER BY o1, o2...

महत्वपूर्ण बिंदु:

  • आदेश द्वारा समान होना चाहिए
  • @limit पुनः प्राप्त करने के लिए परिणामों की संख्या के साथ प्रतिस्थापित किया जा सकता है,
  • @offset छोड़ने के लिए परिणामों की संख्या है
  • कृपया पिछले समाधानों के साथ प्रदर्शन की तुलना करें क्योंकि वे अधिक कुशल हो सकते हैं
  • यह समाधान डुप्लिकेट whereऔर order byक्लॉज़ करता है, और यदि वे सिंक से बाहर हैं तो गलत परिणाम प्रदान करेंगे
  • दूसरी ओर order byअगर वहाँ है कि क्या जरूरत है स्पष्ट रूप से है

1
-- @RowsPerPage  can be a fixed number and @PageNumber number can be passed 
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 2

SELECT *

FROM MemberEmployeeData

ORDER BY EmployeeNumber

OFFSET @PageNumber*@RowsPerPage ROWS

FETCH NEXT 10 ROWS ONLY

1

विशेष रूप से SQL-SERVER के लिए आप कई अलग-अलग तरीकों से इसे प्राप्त कर सकते हैं। वास्तविक उदाहरण दिए जाने पर हमने यहां ग्राहक तालिका ली।

उदाहरण 1: "सेट रोवेस्ट" के साथ

SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName

सभी पंक्तियों को वापस करने के लिए, ROWCOUNT को 0 पर सेट करें

SET ROWCOUNT 0  
SELECT CustomerID, CompanyName from Customers
    ORDER BY CompanyName

उदाहरण 2: "ROW_NUMBER और OVER" के साथ

With Cust AS
( SELECT CustomerID, CompanyName,
ROW_NUMBER() OVER (order by CompanyName) as RowNumber 
FROM Customers )
select *
from Cust
Where RowNumber Between 0 and 10

उदाहरण 3: "OFFSET और FETCH" के साथ, लेकिन इसके साथ "ORDER BY" अनिवार्य है

SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY

आशा है कि यह आपकी मदद करता है।


-1

SQL सर्वर में आप ROW_NUMBER () के साथ TOP का उपयोग करेंगे


-1

चूंकि, मैं इस स्क्रिप्ट को 1 मिलियन रिकॉर्ड्स से अधिक उपयोगी बनाता हूं, प्रत्येक पेज 100 रिकॉर्ड्स के साथ पृष्ठांकन कार्य तेजी से करता है, मेरा पीसी इस स्क्रिप्ट को 0 सेकंड में निष्पादित करता है, जबकि mysql के साथ तुलना करने की अपनी सीमा होती है और परिणाम प्राप्त करने के लिए लगभग 4.5 सेकंड ऑफसेट करते हैं।

किसी को Row_Number () को हमेशा विशिष्ट क्षेत्र द्वारा क्रमबद्ध करने की समझ हो सकती है। मामले में हमें अनुक्रम में केवल पंक्ति को परिभाषित करना चाहिए जिसका उपयोग करना चाहिए:

ROW_NUMBER () OVER (ORDER BY (Select NULL))

SELECT TOP {LIMIT} * FROM (
      SELECT TOP {LIMIT} + {OFFSET} ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ROW_NO,*
      FROM  {TABLE_NAME}
) XX WHERE ROW_NO > {OFFSET}

के बारे में बताएं:

  • {LIMIT}: प्रत्येक पृष्ठ के लिए रिकॉर्ड की संख्या
  • {OFFSET}: स्किप रिकॉर्ड की संख्या

2
हालांकि यह कोड प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है, इससे वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद मिलेगी, और संभवत: अधिक वोट मिले। याद रखें कि आप भविष्य में पाठकों के लिए सवाल का जवाब दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है। कृपया स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें और संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं।
ब्रायन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.