2011-09-07 32 views
20

Tôi có hai cột là người đầu tiên tôi muốn 10 sản phẩm hàng đầu (1-10)Máy chủ SQL Chọn 10-20 kết quả hàng đầu?

Đó là

SELECT TOP 10 * FROM Product 

Trong cột thứ hai tôi muốn 10 kết quả tiếp theo (11-20)

Tôi làm như thế nào?

+1

gì versi trên của SQL Server xin vui lòng? –

+0

MySql hoặc SQLServer nền tảng gì? – Hogan

+0

@Nicklas Truy cập vào các chủ đề sau: http://stackoverflow.com/questions/216673/emulate-mysql-limit-clause-in-microsoft-sql-server-2000 http: // stackoverflow.com/questions/364292/sql-server-2005-select-top-n-plus-other – adatapost

Trả lời

27
WITH T AS 
(
SELECT TOP 20 name, 
     row_number() OVER (ORDER BY id) AS RN 
FROM Products 
ORDER BY id 
) 
SELECT 
     MAX(CASE WHEN RN <=10 THEN name END) AS Col1, 
     MAX(CASE WHEN RN > 10 THEN name END) AS Col2 
FROM T  
GROUP BY RN % 10 
+3

Tôi phải thừa nhận bao nhiêu tôi thích đọc của Martin và giải pháp của Marc. 1 cho cả hai – niktrs

+2

+1 darn - điều này thậm chí còn thông minh hơn nhiều và ít hơn "thuế" trên kế hoạch thực hiện so với giải pháp của tôi - chúc mừng! –

+1

@marc_s đây là ý tôi thích đọc sách. Các cách tiếp cận và giải pháp khác nhau khiến tôi (ít nhất) suy nghĩ theo cách tốt hơn :) – niktrs

1
SELECT * FROM Product LIMIT(10,10) 
+9

Máy chủ SQL không có 'LIMIT' –

+0

Phụ thuộc vào máy chủ sql – tonekk

+3

Không có phiên bản hoặc ấn bản nào của SQL Server hỗ trợ' LIMIT' - đó là đặc sản tùy chỉnh của MySQL - không phải bất kỳ loại tiêu chuẩn nào ở tất cả –

4

Trong SQL Server, hơi khó để thực hiện việc này. Nếu bạn đang ở trên SQL Server 2005 hoặc mới hơn, bạn có thể sử dụng một CTE với một CROSS JOIN và một số thủ đoạn gian trá để có được những kết quả mà bạn đang tìm kiếm:

;WITH TopProducts AS 
(
    SELECT 
     ProductID, ProductName, 
     ROW_NUMBER() OVER(ORDER BY --some-column-here-- DESC) 'RN' 
    FROM dbo.Products 
) 
SELECT 
    p1.ProductID, p1.ProductName, 
    p2.ProductID, p2.ProductName 
FROM 
    TopProducts p1 
CROSS JOIN 
    TopProducts p2 
WHERE 
    p1.RN BETWEEN 1 AND 10  -- get rows 1-10 from the first CTE 
    -- AND p2.RN BETWEEN 11 AND 20 redundant, as niktrs pointed out 
    AND p1.RN + 10 = p2.RN  -- join rows from P1 and P2 so you don't get a cartesian product 

Những con số các sản phẩm CTE (Bảng Common Expression) - điều này cần phải dựa trên một số cột từ bảng Products của bạn, nhưng bạn không đề cập đến cột nào xác định thứ tự.

Sau đó, chúng tôi chọn các hàng 1-10 từ CTE, cũng như các hàng 11-20 từ phiên bản thứ hai của CTE. Nếu bạn để nguyên giá trị này, bạn sẽ nhận được 100 hàng - mỗi kết hợp của các hàng 1-10 từ tập hợp kết quả đầu tiên đối với mỗi hàng trong số 10 hàng từ tập kết quả thứ hai.

Đó là lý do tại sao bạn cần thêm điều kiện, dựa trên số hàng, để "nối" một hàng từ mỗi tập kết quả và do đó bạn sẽ nhận được mười hàng - cột đầu tiên có các mục từ 1-10 từ Sản phẩm bảng, cột thứ hai có hàng 11-20

+1

Mặc dù tôi nghĩ rằng điều này sẽ thực hiện tốt hơn mã của tôi, trong môi trường thử nghiệm của tôi làm cho hai quét chỉ mục thay vì tìm kiếm chỉ mục ?! Ngoài ra tôi nghĩ VÀ p2.RN GIỮA 11 VÀ 20 là redudant vì AND p1.RN + 10 = p2.RN – niktrs

+1

@niktrs: bạn nói đúng về sự thừa - thậm chí có thể viết nó như là một INNER JOIN và đặt nó p1.RN = p2.RN - 10' là điều kiện JOIN - hoạt động quá –

+0

@marc_s: Về mặt logic này * là * một tham gia bên trong, tôi nghĩ vậy. Dù sao, 1, nó làm công việc của mình đúng. –

2

tôi không chắc chắn đây là cách tốt nhất để làm điều đó nhưng nó hoạt động

select * 
from 
(
SELECT top 10 ROW_NUMBER() OVER(ORDER BY product) linenum, product 
FROM products 
) t1 
JOIN 
(
SELECT top 20 ROW_NUMBER() OVER(ORDER BY product) linenum, product 
FROM products 
) t2 ON t1.linenum+10 = t2.linenum 
+0

Tôi nghĩ rằng điều này sẽ dẫn đến 10 hàng đầu tiên được hiển thị hai lần, trong cả hai cột, một lần và một lần cùng với nhau 10. Có thể bạn có nghĩa là 'INNER JOIN' thay vì' FULL JOIN'? Hay tôi đang thiếu một cái gì đó? –

+0

Có. cảm ơn cho các bình luận – niktrs

1

Hãy thử điều này một:

SELECT * 
FROM 
( 
    SELECT TOP 10 ROW_NUMBER() OVER(ORDER BY ColName) RowNo, ColName 
    FROM TableName 
) table1 
INNER JOIN 
( 
    SELECT TOP 20 ROW_NUMBER() OVER(ORDER BY ColName) RowNo, ColName 
    FROM TableName 
) table2 ON table1.RowNo + 10 = table2.RowNo 
7

tôi sẽ làm điều này:

SELECT [columns] FROM [table names] ORDER BY [column name] DESC LIMIT 10 OFFSET 10; 

Đây là đơn giản hơn và ít phức tạp ....

Các bạn nghĩ gì?

+9

Không hoạt động với máy chủ SQL – gaffcz

2
declare @FromRange int 
declare @ToRange int 
set @FromRange =11 
set @ToRange =20 
SELECT top(@[email protected]+1) * FROM [tbl] 
where tbl_id not in (select top (@FromRange-1) tbl_id from tbl) 
ORDER BY tbl_id 
+0

câu trả lời tuyệt vời cho tôi –

+0

Câu trả lời hay nhất cho tôi. Cảm ơn rất nhiều – Nisha

+0

chọn đầu (@ FromRange-1) tbl_id từ tbl * ORDER BY tbl_id * bắt buộc đối với truy vấn thứ hai quá – SoulRayder

7
select top 10 wwwhid from wwwh where wwwhid not in(select top 10 wwwhid from wwwh) 
1
WITH result_set AS 
    (SELECT ROW_NUMBER() OVER 
     (ORDER BY Product.ID DESC) AS 
    [row_number], Product.intId AS id, Product.Title As Title 
    FROM Product WHERE Product.Price > 11) 
SELECT * FROM result_set WHERE [row_number] BETWEEN 10 AND 19 
0
SELECT p.* FROM 
(
SELECT *, ROW_NUMBER() OVER (ORDER BY /*some column*/) AS row_num 
FROM Product 
) AS p 
WHERE p.row_num BETWEEN 11 AND 20 
0
select * 
from (select * 
     from <table> 
     order by id asc) 
where rownum <= 20 

minus 
select * 
from (select * 
     from <table> 
     order by id asc) 
where rownum <= 10 
+0

Chào mừng bạn đến với Stack Overflow :-) Hãy tham gia [tour] – Breeze

0

Hãy thử điều này:

SELECT * FROM 
    (SELECT ROW_NUMBER() OVER (ORDER BY ColumnName) AS MyRowNumber, * 
    FROM TableName) tbl 
WHERE MyRowNumber BETWEEN 20 AND 30 
1

Sử dụng mã:

select top 20 * from [table Name] 
except 
select top 10 * from [table Name] 
Các vấn đề liên quan