6 Stimmen

Kann ich count() und rows von einer Sql-Abfrage im Sql-Server erhalten?

Ich möchte die Gesamtzahl der Ergebnisse und die ersten n Zeilen einer Abfrage zu erhalten - ist es möglich in einer einzigen Anweisung?

Ich würde die Ergebnisse wie folgt erwarten:

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

Vielen Dank im Voraus!

8voto

gbn Punkte 407102

Zum Beispiel so:

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

Edit: Nach Downvote und COUNT/OVER Antwort. Ein Vergleich auf 2 Tabellen von mir

Sie können einen großen Unterschied zwischen meinem CROSS JOIN/einfachen Aggregat und einer COUNT/leeren ORDER BY-Klausel erkennen

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]))

Ich habe dies an einer Tabelle mit 570k Zeilen wiederholt, und hier ist das 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.

6voto

Chris Bednarski Punkte 3052

Was ist mit

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

Betreffend CROSS JOIN Abfragen
In einem schweren INSERT / DELETE Umgebung, gibt die Kreuzverknüpfung eine falsche Zeilenzahl zurück.

Versuchen Sie dies über mehrere Verbindungen
Verbindung 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;

Verbindung 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

Jedes Mal wird die Anzahl der Datensätze ( @@ROWCOUNT ) ist anders als T2.cnt

Im Fall von COUNT(*) OVER() gibt es nur einen einzigen Tabellenscan und die @@ROWCOUNT ist immer gleichbedeutend mit T2.cnt

In Bezug auf Abfragepläne - SQL 2005 SP3 scheint viel schwächer zu sein, wenn es darum geht COUNT(*) OVER() als SQL 2008 R2. Darüber hinaus werden die Abfragekosten nicht korrekt angegeben (ich hätte nie gedacht, dass eine Unterabfrage mehr als 100 % der gesamten Abfrage kosten kann).

In vielen Fällen sind die Kosten für die COUNT(*) OVER() liegt zwischen 50-75% des CROSS JOIN

Das beste Szenario für eine Kreuzverknüpfung wäre, wenn es einen sehr engen Index für die Zählung gäbe. Auf diese Weise gibt es einen geclusterten Index-Scan für die Daten + einen Index-Scan für die Zählung.

Wie immer ist es am besten, zu messen, zu messen, zu messen und sich für den Kompromiss zu entscheiden, mit dem man gut leben kann.

3voto

Aaronaught Punkte 118136

Usted peut tun dies mit einer CROSS JOIN und CTE, aber es ist nicht sehr effizient:

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

Ich denke, ein besserer Weg, um das zu erreichen, was Sie wollen, wäre eine einzige Abfrage zu verwenden, aber mehrere Ergebnissätze Dies können Sie tun, indem Sie COMPUTE :

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

0voto

anu Punkte 1

Einen Versuch für diese Abfrage:

select ColumnId,Descr,(select COUNT(*) from ColumnSetUp)as c
from ColumnSetUp
group by ColumnId,Descr

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X