2010-05-09 43 views
6

Tôi muốn nhận tổng số kết quả và n hàng đầu của một số truy vấn - có thể trong một tuyên bố không?Tôi có thể nhận số() và các hàng từ một truy vấn sql trong máy chủ sql không?

tôi mong đợi những kết quả như sau:

count(..) column1  column2 
125   some_value some_value 
125   some_value some_value 

Cảm ơn bạn trước!

+0

có thể. Vui lòng tham khảo liên kết dưới đây. http://stackoverflow.com/questions/610932/how-to-retrieve-the-total-row-count-of-a-query-with-top – Sahi

Trả lời

3

Bạn có thể làm điều này với một CROSS JOIN và CTE, nhưng nó không phải là rất hiệu quả:

WITH Rows_CTE AS 
(
    SELECT Column1, Column2 
    FROM Table 
    WHERE (...) 
) 
SELECT c.Cnt, r.Column1, r.Column2 
FROM Rows_CTE r 
CROSS JOIN (SELECT COUNT(*) AS Cnt FROM Rows_CTE) c 

Tôi nghĩ rằng một cách tốt hơn để có được những gì bạn muốn sẽ được sử dụng một truy vấn duy nhất nhưng nhiều kết quả đặt, mà bạn có thể thực hiện bằng cách sử dụng COMPUTE:

SELECT Column1, Column2 
FROM Table 
WHERE (...) 
COMPUTE COUNT([Column1]) 
+0

Tại sao nên sử dụng CTE? Một tham gia chéo đơn giản vào một bảng có nguồn gốc sẽ làm điều đó. Và COMPUTE cũng không còn được dùng nữa. – gbn

+0

@gbn: Tôi đã sử dụng 'CROSS JOIN'. CTE là để các biến vị ngữ có thể được tái sử dụng (lưu ý sự bao gồm của 'WHERE (...)', thiếu từ câu hỏi nhưng có thể được bao gồm trong môi trường sản xuất). Và tôi biết 'COMPUTE' về mặt kỹ thuật không được chấp nhận, nhưng' ROLLUP' không thể thay thế nó ở đây và sử dụng 'COMPUTE' loại bỏ toàn bộ bảng/chỉ mục quét khỏi kế hoạch. – Aaronaught

+0

Thành thật mà nói, nó luôn làm tôi khó chịu vì họ không dùng 'COMPUTE', bởi vì nó vẫn là cách duy nhất để tính toán tổng hợp mà không có mệnh đề' GROUP BY'. Nhưng đó là một lời rên rỉ cho một ngày khác. – Aaronaught

8

như thế này:

SELECT TOP 100 --optional 
    MC.Cnt, M.Column1, M.Column2 
FROM 
    myTable M 
    CROSS JOIN 
    (SELECT COUNT(*) AS Cnt FROM myTable) MC 

Chỉnh sửa: Sau câu trả lời và câu trả lời COUNT/OVER. Một so sánh về 2 bảng của tôi

Bạn có thể thấy một sự khác biệt rất lớn giữa CHÉO tôi THAM GIA/tổng hợp đơn giản và một COUNT/TRÌNH TỰ trống BY khoản

SELECT COUNT(*) OVER() AS C, key1col, key2col 
FROM myTable 

(24717 row(s) affected) 

Table 'Worktable'. Scan count 3, logical reads 49865, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'myTable'. Scan count 1, logical reads 77, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

StmtText 
    |--Nested Loops(Inner Join) 
     |--Table Spool 
     | |--Segment 
     |   |--Index Scan(OBJECT:([MyDB].[dbo].[myTable].[IX_useful])) 
     |--Nested Loops(Inner Join, WHERE:((1))) 
      |--Compute Scalar(DEFINE:([Expr1003]=CONVERT_IMPLICIT(int,[Expr1005],0))) 
      | |--Stream Aggregate(DEFINE:([Expr1005]=Count(*))) 
      |   |--Table Spool 
      |--Table Spool 

SELECT 
    MC.Cnt, M.key1col, M.key2col 
FROM 
    myTable M 
    CROSS JOIN 
    (SELECT COUNT(*) AS Cnt FROM myTable) MC 

(24717 row(s) affected) 

Table 'myTable'. Scan count 2, logical reads 154, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


StmtText 
    |--Nested Loops(Inner Join) 
     |--Compute Scalar(DEFINE:([Expr1005]=CONVERT_IMPLICIT(int,[Expr1009],0))) 
     | |--Stream Aggregate(DEFINE:([Expr1009]=Count(*))) 
     |   |--Index Scan(OBJECT:([MyDB].[dbo].[myTable].[IX_useful])) 
     |--Index Scan(OBJECT:([MyDB].[dbo].[myTable].[IX_useful] AS [M])) 

tôi đã lặp đi lặp lại này trên một bảng với 570k hàng và đây là IO

Table 'Worktable'. Scan count 3, logical reads 1535456, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'myTable'. Scan count 1, logical reads 2929, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


Table 'myTable'. Scan count 34, logical reads 6438, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
+0

+1 để kéo tất cả súng của bạn ra. Tôi sẽ phải kiểm tra kế hoạch thực hiện của tôi. –

+0

@Chris Bednarski: Tôi đã bị cắn trước đó! Ngoài ra SET THỐNG KÊ THỜI GIAN TRÊN si hữu ích: CPU là x5 đến x10 và thời gian x2 cho giải pháp OVER cho tôi – gbn

+0

@gbn: Bây giờ tôi quan tâm để xem liệu có sự khác biệt về hiệu suất giữa năm 2005 và 2008. Nó chạy như một con chó vào năm 2005. –

6

gì về

SELECT COUNT(*) OVER() AS C, COLUMN1, COLUMN2 
FROM TABLE 

về CROSS JOIN truy vấn
Trong môi trường nặng INSERT/DELETE, tham gia chéo sẽ trả về số lượng hàng không chính xác.

Hãy thử điều này từ nhiều kết nối
kết nối 1

set nocount on; 
drop table dbo.test_table; 
GO 
create table dbo.test_table 
(
    id_field uniqueidentifier not null default(newid()), 
    filler char(2000) not null default('a') 
); 
GO 
create unique clustered index idx_id_fld on dbo.test_table(id_field); 
GO 
while 1 = 1 
insert into dbo.test_table default values; 

kết nối 2

select T2.cnt, T1.id_field, T1.filler 
from dbo.test_table T1 
cross join (select COUNT(*) as cnt from dbo.test_table) T2 

select T2.cnt, T1.id_field, T1.filler 
from dbo.test_table T1 
cross join (select COUNT(*) as cnt from dbo.test_table) T2 

select T2.cnt, T1.id_field, T1.filler 
from dbo.test_table T1 
cross join (select COUNT(*) as cnt from dbo.test_table) T2 

Mỗi lần, số lượng hồ sơ (@@ROWCOUNT) là khác nhau để T2.cnt

Trong trường hợp của COUNT(*) OVER(), chỉ có một lần quét bảng duy nhất và @@ROWCOUNT luôn giống như T2.cnt

Về kế hoạch truy vấn - SQL 2005 SP3 có vẻ yếu hơn nhiều khi thực hiện COUNT(*) OVER() so với SQL 2008 R2. Ngày đầu đó, nó báo cáo không chính xác chi phí truy vấn (tôi không bao giờ nghĩ rằng một truy vấn phụ có thể chi phí hơn 100% của toàn bộ truy vấn).

Trong rất nhiều tình huống, chi phí của COUNT(*) OVER() là giữa 50-75% của CROSS JOIN

Trường hợp kịch bản tốt nhất cho một chéo tham gia sẽ là nếu có một chỉ số rất hẹp để thực hiện đếm trên .Bằng cách đó sẽ có một quét chỉ mục nhóm cho dữ liệu + quét chỉ mục để đếm.

Như mọi khi, tốt nhất là đo lường, đo lường, đo lường và đi theo thỏa hiệp mà bạn hài lòng khi sống.

+0

Tôi sẽ đề xuất cùng một điều (ish) –

+0

+1 để sử dụng chức năng Phân tích ..... –

+0

tốt hơn nhiều so với kết nối, sử dụng một lần quét duy nhất –

0

đưa ra một thử cho truy vấn này:

select ColumnId,Descr,(select COUNT(*) from ColumnSetUp)as c 
from ColumnSetUp 
group by ColumnId,Descr 
Các vấn đề liên quan