it-swarm.com.de

Warum sind Zahlentabellen "von unschätzbarem Wert"?

Unser Bewohner Datenbankexperte sagt uns, dass Zahlentabellen von unschätzbarem Wert sind . Ich verstehe nicht ganz warum. Hier ist eine Zahlentabelle:

USE Model
GO

CREATE TABLE Numbers
(
    Number INT NOT NULL,
    CONSTRAINT PK_Numbers 
        PRIMARY KEY CLUSTERED (Number)
        WITH FILLFACTOR = 100
)

INSERT INTO Numbers
SELECT
    (a.Number * 256) + b.Number AS Number
FROM 
    (
        SELECT number
        FROM master..spt_values
        WHERE 
            type = 'P'
            AND number <= 255
    ) a (Number),
    (
        SELECT number
        FROM master..spt_values
        WHERE 
            type = 'P'
            AND number <= 255
    ) b (Number)
GO

Laut Blog-Beitrag lautet die Begründung

Zahlentabellen sind wirklich von unschätzbarem Wert. Ich benutze sie die ganze Zeit für die Manipulation von Strings, die Simulation von Fensterfunktionen, das Auffüllen von Testtabellen mit vielen Daten, das Eliminieren der Cursorlogik und viele andere Aufgaben, die ohne sie unglaublich schwierig wären.

Aber ich verstehe nicht genau, was diese Verwendungszwecke sind - können Sie einige überzeugende, spezifische Beispiele dafür liefern, wo eine "Zahlentabelle" Ihnen eine Menge Arbeit in SQL Server erspart - und warum wir sie haben sollten?

112
Jeff Atwood

Ich habe viele Anwendungen gesehen, wenn Sie "fehlende Daten" projizieren müssen. Z.B. Sie haben eine Zeitreihe (z. B. ein Zugriffsprotokoll) und möchten die Anzahl der Treffer pro Tag in den letzten 30 Tagen anzeigen (Think Analytics Dashboard). Wenn Sie eine select count(...) from ... group by day ausführen, erhalten Sie die Zählung für jeden Tag, aber das Ergebnis enthält nur eine Zeile für jeden Tag, an dem Sie tatsächlich mindestens einen Zugriff hatten. Wenn Sie andererseits zuerst eine Tabelle mit Tagen aus Ihrer Zahlentabelle (select dateadd(day, -number, today) as day from numbers) projizieren und dann mit den Zählungen verknüpfen (oder äußerlich anwenden, was auch immer Sie möchten), erhalten Sie ein Ergebnis mit 0 für die Anzahl der Tage, an denen Sie keinen Zugriff hatten. Dies ist nur ein Beispiel. Natürlich kann man argumentieren, dass die Präsentationsebene Ihres Dashboards die fehlenden Tage verarbeiten und stattdessen nur eine 0 anzeigen könnte, aber einige Tools (z. B. SSRS) können dies einfach nicht verarbeiten.

Andere Beispiele, die ich gesehen habe, verwendeten ähnliche Zeitreihentricks (Datum/Uhrzeit +/- Nummer), um alle Arten von Fensterberechnungen durchzuführen. Wenn Sie in einer imperativen Sprache eine for-Schleife mit einer bekannten Anzahl von Iterationen verwenden, kann die deklarative und festgelegte Natur von SQL im Allgemeinen einen Trick verwenden, der auf einer Zahlentabelle basiert.

Übrigens, ich habe das Bedürfnis, die Tatsache herauszustellen, dass, obwohl eine Zahlentabelle verwendet wird, sich anfühlt wie eine zwingende prozedurale Ausführung, nicht in den Irrtum geraten, anzunehmen, dass es ist zwingend erforderlich. Lassen Sie mich ein Beispiel geben:

int x;
for (int i=0;i<1000000;++i)
  x = i;
printf("%d",x);

Dieses Programm gibt 999999 aus, das ist so ziemlich garantiert.

Versuchen wir dasselbe in SQL Server unter Verwendung einer Zahlentabelle. Erstellen Sie zunächst eine Tabelle mit 1.000.000 Zahlen:

create table numbers (number int not null primary key);
go

declare @i int = 0
    , @j int = 0;

set nocount on;
begin transaction
while @i < 1000
begin
    set @j = 0;
    while @j < 1000
    begin
        insert into numbers (number) 
            values (@j*[email protected]);
        set @j += 1;
    end
    commit;
    raiserror (N'Inserted %d*1000', 0, 0, @i)
    begin transaction;
    set @i += 1;
end
commit
go

Lassen Sie uns nun die 'for-Schleife' ausführen:

declare @x int;
select @x = number 
from numbers with(nolock);
select @x as [@x];

Das Ergebnis ist:

@x
-----------
88698

Wenn Sie jetzt einen WTF-Moment haben (schließlich ist number der gruppierte Primärschlüssel!), Heißt der Trick - Zuordnungsreihenfolge-Scan und ich habe nicht versehentlich @j*[email protected] Eingefügt ... Sie hätten auch eine Vermutung wagen und sagen können, das Ergebnis sei Parallelität und das manchmal may sei die richtige Antwort.

Es gibt viele Trolle unter dieser Brücke und ich erwähnte einige in Kurzschluss des booleschen Operators auf SQL Server und T-SQL-Funktionen implizieren keine bestimmte Reihenfolge von Ausführung

82
Remus Rusanu

Ich habe eine Zahlentabelle gefunden, die in einer Vielzahl von Situationen sehr nützlich ist.

Bei Warum sollte ich die Verwendung einer Hilfszahlentabelle in Betracht ziehen? , geschrieben im Jahr 2004, zeige ich einige Beispiele:

  • Eine Zeichenfolge analysieren
  • Identitätslücken finden
  • Generieren von Datumsbereichen (z. B. Auffüllen einer Kalendertabelle, die ebenfalls von unschätzbarem Wert sein kann)
  • Zeitscheiben generieren
  • IP-Bereiche generieren

Bei Schlechte Gewohnheiten beim Treten: Verwenden von Schleifen zum Auffüllen großer Tabellen zeige ich, wie eine Zahlentabelle verwendet werden kann, um viele Zeilen in kurzer Zeit einzufügen (im Gegensatz zum Knie-Ruck-Ansatz der Verwendung eine while-Schleife).

Unter Verarbeiten einer Liste von Ganzzahlen: mein Ansatz und Weitere Informationen zum Aufteilen von Listen: Benutzerdefinierte Trennzeichen, Verhindern von Duplikaten und Beibehalten der Reihenfolge zeige ich, wie eine Zahlentabelle zum Teilen von a verwendet wird Zeichenfolge (z. B. eine Reihe von durch Kommas getrennten Werten) und bieten Leistungsvergleiche zwischen dieser und anderen Methoden. Weitere Informationen zum Teilen und zur Handhabung anderer Zeichenfolgen:

Und in Die SQL Server-Zahlentabelle, erklärt - Teil 1 gebe ich einige Hintergrundinformationen zum Konzept und habe zukünftige Beiträge auf Lager, um bestimmte Anwendungen detailliert darzustellen.

Es gibt viele andere Verwendungszwecke, das sind nur einige, die mir so aufgefallen sind, dass ich darüber schreiben kann.

Und wie bei @gbn habe ich ein paar Antworten zum Stapelüberlauf und auf dieser Site , die ebenfalls eine Zahlentabelle verwenden.

Schließlich habe ich eine Reihe von Blog-Posts über das Generieren von Sets ohne Schleifen, die teilweise den Leistungsvorteil der Verwendung einer Zahlentabelle im Vergleich zu den meisten anderen Methoden zeigen (abgesehen von Remus 'skurrilem Ausreißer):

56
Aaron Bertrand

Hier ist ein großartiges Beispiel, das ich kürzlich von Adam Machanic : verwendet habe

CREATE FUNCTION dbo.GetSubstringCount
(
    @InputString TEXT, 
    @SubString VARCHAR(200),
    @NoisePattern VARCHAR(20)
)
RETURNS INT
WITH SCHEMABINDING
AS
BEGIN
    RETURN 
    (
        SELECT COUNT(*)
        FROM dbo.Numbers N
        WHERE
            SUBSTRING(@InputString, N.Number, LEN(@SubString)) = @SubString
            AND PATINDEX(@NoisePattern, SUBSTRING(@InputString, N.Number + LEN(@SubString), 1)) = 0
            AND 0 = 
                CASE 
                    WHEN @NoisePattern = '' THEN 0
                    ELSE PATINDEX(@NoisePattern, SUBSTRING(@InputString, N.Number - 1, 1))
                END
    )
END

Ich habe etwas Ähnliches mit einem CTE verwendet, um eine bestimmte Instanz von Teilzeichenfolgen zu finden (d. H. "Finde die 3. Pipe in dieser Zeichenfolge"), um mit korrelierten begrenzten Daten zu arbeiten:

declare @TargetStr varchar(8000), 
@SearchedStr varchar(8000), 
@Occurrence int
set @TargetStr='a'
set @SearchedStr='abbabba'
set @Occurrence=3;

WITH Occurrences AS (
SELECT Number,
       ROW_NUMBER() OVER(ORDER BY Number) AS Occurrence
FROM master.dbo.spt_values
WHERE Number BETWEEN 1 AND LEN(@SearchedStr) AND type='P'
  AND SUBSTRING(@SearchedStr,Number,LEN(@TargetStr))[email protected])
SELECT Number
FROM Occurrences
WHERE [email protected]

Wenn Sie keine Zahlentabelle haben, können Sie alternativ eine Schleife verwenden. Grundsätzlich können Sie mit einer Zahlentabelle eine satzbasierte Iteration ohne Cursor oder Schleifen durchführen.

26
JNK

Ich würde eine Zahlentabelle verwenden, wenn ich ein SQL-Äquivalent von Enumerable.Range benötige. Zum Beispiel habe ich es gerade in einer Antwort auf dieser Site verwendet: Berechnung der Anzahl der Permutationen

12
A-K