2012-04-30 19 views
5

sein könnte Ich habe eine SQL Server-Tabelle AccountAction die denormalized ist. Es ist eine verflachte Version der Account und Action Tabellen, die ich hoffe, sollte für das Melden von Abfragen über Millionen von Zeilen viel schneller sein. Ein Account kann viele Actions haben, so dass die Tabelle ähnelt:SQL, um X Anzahl der Konten von der DB zu bekommen, die Variable Anzahl der Zeilen

Account  Action 
account1 action1 
account1 action2 
account1 action10 
account2 action5 

aber ich einige Probleme, die Informationen zurück für eine begrenzte Teilmenge in einem einfachen Stored Procedure zu bekommen.

select Account, Action 
from AccountAction 
where ??? 

Was ich suche ist, um die ersten X-Konten mit all ihren Aktionen zu bekommen. Dies wird eine dynamische Anzahl von Zeilen sein. Wenn ich also die obige Beispieltabelle nutze, würde ich 3 Zeilen erhalten (d. H., Geben Sie mir alle Zeilen für das erste Konto).

(ich habe nichts dagegen, dass der Kontoname in jeder Reihe sein wird - es wird an anderer Stelle geschwenkt)

Habe ich eine ROWNUM oder ähnliches verwenden müssen, um die Zeilen zu beschränken? Ich bin sicher, das muss ein einfacheres Problem sein, als ich bisher gefunden habe.

EDIT

Die Antworten TOP verwendet wird, würde ich in dem Beispiel nicht funktionieren werden wollen 3 Reihen zurück, wenn ich sagte ‚mir geben eine (erste) Konto‘. Aber woher weiß ich, dass es 3 sein wird? Seine Dynamik. Sie können auch nicht sequenziell sein, was wäre, wenn account1s Aktion99 in den Ergebnissen bei 55 Millionen lag.

Antwort

4
WITH 
    SequencedData 
AS 
(
    SELECT 
    DENSE_RANK() OVER (ORDER BY Account) AS account_sequence_id, 
    * 
    FROM 
    AccountAction 
) 
SELECT 
    * 
FROM 
    SequenceData 
WHERE 
    account_sequence_id = ??? 

Oder, für vielfache ...

WHERE 
    account_sequence_id BETWEEN 3 AND 5 -- For the 3rd, 4th and 5th accounts. 
+0

Das hört sich gut an, obwohl die Leistung über z.B. 100m Reihen? Es wird den Rang in jeder Reihe zuerst richtig machen müssen? – finoutlook

+1

@finoutlook - Es kommt darauf an. Alles, was * tatsächlich * benötigt wird, ist, die Daten in der Reihenfolge "Account" zu haben. Einmal bestellt, kann der Optimierer nur die "N-te" -Instanz davon suchen. Hast du schon einen Index mit "Account" als erstes Feld? Wenn dies der Fall ist, sind die Daten bereits geordnet und Sie verarbeiten nur die Mindestanzahl von Datensätzen. Wenn nicht, füge eins hinzu;) – MatBailie

+0

Cool, ich hatte nicht daran gedacht, sie vorher zu bestellen. Ich könnte das als Teil der Synchronisierung mit der de-normalisierten Tabelle tun. – finoutlook

0

Wenn ich habe die Frage richtig dann, wenn u dann

SELECT TOP 10 Account, Action 
FROM AccountAction 

verwenden ersten 10 Zeilen auswählen möchten oder wenn u wollen einige anfängliche 20 Prozent Aufzeichnungen dann Nutzungs-

SELECT TOP 10 PERCENT Account, Action 
FROM AccountAction 
+0

Die OP das 'Nth' Konto will, wo jedes Konto eine andere Nummer haben kann zeichnet jeden auf. – MatBailie

0

haben Sie TOP versucht?

declare @hoW_many int 
set @hoW_many = 10 

select top (@hoW_many) * 
from AccountAction 
+0

Das OP will nicht die 'ersten N Zeilen', das OP will das' Nth Account', wobei jedes Konto eine andere Anzahl von Zeilen hat. – MatBailie

1
SELECT * 
FROM AccountAction 
WHERE account IN (SELECT account 
    FROM AccountAction 
    GROUP BY account HAVING account BETWEEN *start-account* AND *end-account* 
    ORDER BY account 
) 

Erläuterung: Die Unterabfrage Gruppen von den verschiedenen Konten (und ermöglicht eine feinere Selektionskriterien als eine einfache DISTINCT) und gibt nur die Konten. Das äußere SELECT erhält eine variable Anzahl von Zeilen, abhängig von den einzelnen Konten, die von der Unterabfrage abgerufen werden.

EDIT: Das obige nimmt an, dass man durch das account Feld in AccountAction Tabelle filtern kann; Dies ist normalerweise der Fall in Tabellen, die eine M:N Beziehung auf DB-Ebene verbinden.

+2

'LIMIT' ist keine SQL-Server-Funktion. – GarethD

+0

@GarethD Danke mein Code aktualisiert, um 'TOP' stattdessen mit dem gleichen Effekt von' LIMIT' zu verwenden. –

+0

Nachtrag von LIMIT nach TOP - Was ist, wenn das OP den 3., 4. und 5. benötigt? Ich werde +1, wenn Sie diese Änderung auch machen :) – MatBailie

0

Ein einfaches Unterauswahl mit top Schlüsselwort (und unterschiedliches), würden Sie alle Aktionen für die ersten X-Konten

select * from AccountAction 
where Account in 
(select distinct top (@NumberOfAccounts) Account 
from AccountAction order by Account) 
+1

Sie benötigen eine ORDER BY in der Unterabfrage sonst die Ergebnisse können von Ausführung zu Ausführung variieren. Dann ist es das selbe wie die Antwort von JosvicZammit, 6 Minuten vor Ihrem * (wo DISTINCT und GROUP BY austauschbar sind) *. – MatBailie

+0

@Dems - Antwort geändert, um ORDER BY einzuschließen; aber meine Absicht war nicht, eine doppelte Antwort aufzunehmen ... –

Verwandte Themen