2008-10-23 20 views
7

में ROW_NUMBER() OVER() का उपयोग करके विभिन्न कॉलम पर सॉर्टिंग का उपयोग करके पेजिनेटेड क्वेरी का मानना ​​है कि मान लें कि मैं नॉर्थविंड डेटाबेस का उपयोग कर रहा हूं और मैं अन्य पैरामीटर के बीच एक संग्रहीत प्रक्रिया के माध्यम से एक क्वेरी चलाने के लिए चाहता हूं, निम्नलिखित:एसक्यूएल सर्वर 2005

  • @Offset इंगित करने के लिए जहां पृष्ठांकन शुरू होता है,
  • @Limit पृष्ठ आकार से संकेत मिलता है,
  • @SortColumn छँटाई उद्देश्यों के लिए इस्तेमाल स्तंभ इंगित करने के लिए,
  • @SortDirection, ascendant या वंशज सॉर्टिंग इंगित करने के लिए।

विचार डेटाबेस पर पेजिनेशन करना है, क्योंकि परिणाम सेट में हजारों पंक्तियां हैं इसलिए कैशिंग एक विकल्प नहीं है (और VIEWSTATE का उपयोग करके आईएमओ, बेकार भी नहीं माना जाता है)।

आप SQL सर्वर 2005 बता दें कि समारोह ROW_NUMBER जो एक परिणाम के सेट के एक विभाजन के भीतर एक पंक्ति के अनुक्रमिक संख्या देता है, प्रत्येक विभाजन में पहली पंक्ति के लिए 1 से शुरू प्रदान करता है।

हमें प्रत्येक लौटा कॉलम (इस उदाहरण में पांच) पर क्रमबद्ध करने की आवश्यकता है और गतिशील एसक्यूएल एक विकल्प नहीं है, इसलिए हमारे पास दो संभावनाएं हैं: IF ... ELSE ... का उपयोग करके और 10 प्रश्न हैं, जो बनाए रखने के लिए नरक है, या निम्नलिखित की तरह क्वेरी:

WITH PaginatedOrders AS (
    SELECT 
     CASE (@SortColumn + ':' + @SortDirection) 
      WHEN 'OrderID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC) 
      WHEN 'OrderID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC) 
      WHEN 'CustomerID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID ASC) 
      WHEN 'CustomerID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID DESC) 
      WHEN 'EmployeeID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID ASC) 
      WHEN 'EmployeeID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID DESC) 
      WHEN 'OrderDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate ASC) 
      WHEN 'OrderDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate DESC) 
      WHEN 'ShippedDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC) 
      WHEN 'ShippedDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC) 
     END AS RowNumber, 
     OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate 
    FROM Orders 
    -- WHERE clause goes here 
) 
SELECT 
    RowNumber, OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate, 
    @Offset, @Limit, @SortColumn, @SortDirection 
FROM PaginatedOrders 
WHERE RowNumber BETWEEN @Offset AND (@Offset + @Limit - 1) 
ORDER BY RowNumber 

मैं क्वेरी कई बार कोशिश की है, अलग अलग तर्क के साथ, और इसके प्रदर्शन यह वास्तव में काफी अच्छा है, लेकिन यह चित्र है जैसे कि यह किसी अन्य तरीके से अनुकूलित किया जा सकता है लग रहा है।

क्या इस प्रश्न के साथ कुछ गलत है या आप इसे इस तरह से करेंगे? क्या आप एक अलग दृष्टिकोण का प्रस्ताव देते हैं?

+0

मेरा बेवकूफ त्रुटि, तय है कि। कृपया पुन: प्रयास करें। – Tomalak

उत्तर

6

सरल: अगर एएससी क्रम चयन किया जाता है, या इसके विपरीत

SELECT 
    OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate, 
    @Offset, @Limit, @SortColumn, @SortDirection 
FROM 
    Orders 
WHERE 
    ROW_NUMBER() OVER 
    (
    ORDER BY 
     /* same expression as in the ORDER BY of the whole query */ 
) BETWEEN (@PageNum - 1) * @PageSize + 1 AND @PageNum * @PageSize 
    /* AND more conditions ... */ 
ORDER BY 
    CASE WHEN @SortDirection = 'A' THEN 
    CASE @SortColumn 
     WHEN 'OrderID' THEN OrderID 
     WHEN 'CustomerID' THEN CustomerID 
     /* more... */ 
    END 
    END, 
    CASE WHEN @SortDirection = 'D' THEN 
    CASE @SortColumn 
     WHEN 'OrderID' THEN OrderID 
     WHEN 'CustomerID' THEN CustomerID 
     /* more... */ 
    END 
    END DESC 

यह शून्य (DESC) पर सॉर्ट होगा।

ROW_NUMBER() फ़ंक्शन अभिव्यक्ति द्वारा उसी ORDER पर कार्य करने दें।

+0

आज दोपहर मैं परिणामों की तुलना करने के लिए क्वेरी प्लानर और प्रोफाइलर के साथ इस फ़ंक्शन के साथ प्रयास करूंगा :) –

+0

मैं परिणाम देखने के लिए उत्सुक हूं। :-) – Tomalak

+0

बिल्कुल यह एक निम्न त्रुटि देता है: 'संदेश 207, स्तर 16, राज्य 1, रेखा 41 - अमान्य कॉलम नाम' RowNumber '.'। मैं तब एक खंड का उपयोग करूंगा। –

संबंधित मुद्दे