ใช้ฟังก์ชันการเพจ (ข้าม / รับ) กับแบบสอบถามนี้


138

ฉันได้รับการพยายามที่จะเข้าใจเล็กน้อยเกี่ยวกับวิธีการใช้เพจจิ้งที่กำหนดเองใน SQL เช่นการอ่านบทความเช่นนี้

ฉันมีคำถามต่อไปนี้ซึ่งทำงานได้อย่างสมบูรณ์ แต่ฉันต้องการใช้การเพจกับสิ่งนี้

SELECT TOP x PostId FROM ( SELECT PostId, MAX (Datemade) as LastDate
 from dbForumEntry 
 group by PostId ) SubQueryAlias
 order by LastDate desc

ฉันต้องการอะไร

ฉันมีฟอรั่มโพสต์พร้อมรายการที่เกี่ยวข้อง ฉันต้องการรับโพสต์ด้วยรายการที่เพิ่มล่าสุดดังนั้นฉันสามารถเลือกโพสต์ที่ถกเถียงกันล่าสุด

ตอนนี้ฉันต้องการที่จะได้รับ "10 ถึง 20 โพสต์ล่าสุดที่ใช้งานล่าสุด" แทน "top 10"

ฉันลองทำอะไร

ฉันพยายามใช้ฟังก์ชัน ROW เป็นหนึ่งในบทความ แต่จริงๆแล้วไม่มีโชค

มีแนวคิดใดบ้างที่จะนำไปใช้

คำตอบ:


288

ในSQL Server 2012มันง่ายมาก

SELECT col1, col2, ...
 FROM ...
 WHERE ... 
 ORDER BY -- this is a MUST there must be ORDER BY statement
-- the paging comes here
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

ถ้าเราต้องการข้ามคำสั่งซื้อโดยเราสามารถใช้

SELECT col1, col2, ...
  ...
 ORDER BY CURRENT_TIMESTAMP
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

(ฉันค่อนข้างจะทำเครื่องหมายว่าเป็นแฮ็ค - แต่มันถูกใช้เช่นโดย NHibernate หากต้องการใช้คอลัมน์ที่หยิบขึ้นมาอย่างชาญฉลาดเนื่องจาก ORDER BY เป็นวิธีที่ต้องการ)

เพื่อตอบคำถาม:

--SQL SERVER 2012
SELECT PostId FROM 
        ( SELECT PostId, MAX (Datemade) as LastDate
            from dbForumEntry 
            group by PostId 
        ) SubQueryAlias
 order by LastDate desc
OFFSET 10 ROWS -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

คำศัพท์ใหม่offsetและfetch next(เพิ่งทำตามมาตรฐาน SQL) ได้ถูกนำมาใช้

แต่ฉันเดาว่าคุณไม่ได้ใช้SQL Server 2012ใช่ไหม ในรุ่นก่อนหน้านี้มันค่อนข้างยาก (นิดหน่อย) นี่คือการเปรียบเทียบและตัวอย่างสำหรับเซิร์ฟเวอร์ SQL ทุกรุ่น: ที่นี่

ดังนั้นสิ่งนี้สามารถทำงานได้ในSQL Server 2008 :

-- SQL SERVER 2008
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 10,@End = 20;


;WITH PostCTE AS 
 ( SELECT PostId, MAX (Datemade) as LastDate
   ,ROW_NUMBER() OVER (ORDER BY PostId) AS RowNumber
   from dbForumEntry 
   group by PostId 
 )
SELECT PostId, LastDate
FROM PostCTE
WHERE RowNumber > @Start AND RowNumber <= @End
ORDER BY PostId

ขอบคุณมาก! นั่นเป็นคำตอบที่ดีจริงๆ! คำถามเฉพาะเกี่ยวกับ sql 2008 หนึ่ง ฉันต้องการให้ ORDER BY เกิดขึ้นก่อน WHERE ซึ่งจะเรียงลำดับชุดย่อยในปัจจุบัน แต่เราต้องการเลือกบางอย่างจากทั้งชุด ... แนวคิดใดบ้าง :) ขอขอบคุณอีกครั้ง
Lars Holdgaard

2
หากฉันเข้าใจคุณถูกต้องคุณต้องการจัดเรียงตาม LastDate ใช่ไหม จากนั้นเราสามารถเปลี่ยน OVER () clause ด้วยวิธีนี้: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ) และลบคำสั่งซื้อล่าสุดโดย postId ตอนนี้ CTE ควรจะเรียงลำดับ 'เร็วกว่า' ตามต้องการ แก้ไข?
Radim Köhler

1
ขอบคุณสิ่งนี้ช่วยได้โปรดทราบเกี่ยวกับตัวอย่างปี 2012 การสั่งซื้อโดยเป็นข้อบังคับฉันลองใช้โดยไม่มีคำสั่งและได้รับข้อผิดพลาด "ไวยากรณ์ผิด" ไม่ทราบว่ามีอะไรผิดปกติจนกว่าฉันจะดูไวยากรณ์ MSDN และเรียนรู้ว่า .
Esen

เป็นแถวแรก 1 หรือ 0 หรือไม่ ควรที่จะWHERE RowNumber >= @Start AND RowNumber < @Endได้รับ 1,000 แถวแรกถ้า@Startเป็น 0 และ@Endคือ 1,000?
CWSpear

1
ขอบคุณมาก
Mafii

8

ในการทำเช่นนี้ใน SQL Server คุณต้องเรียงลำดับแบบสอบถามตามคอลัมน์เพื่อให้คุณสามารถระบุแถวที่คุณต้องการ

ตัวอย่าง:

select * from table order by [some_column] 
offset 10 rows
FETCH NEXT 10 rows only

และคุณไม่สามารถใช้คำหลัก "TOP" เมื่อทำเช่นนี้

คุณสามารถเรียนรู้เพิ่มเติมได้ที่นี่: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx




-1

คุณสามารถใช้แบบสอบถามซ้อนสำหรับการแบ่งหน้าดังนี้

เพจจิ้งจาก 4 แถว 8 แถวที่รหัสลูกค้าเป็นคีย์หลัก

SELECT Top 5 * FROM Customers
WHERE Country='Germany' AND CustomerId Not in (SELECT Top 3 CustomerID FROM Customers
WHERE Country='Germany' order by city) 
order by city;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.