Nasz ekspert w dziedzinie bazy danych mówi nam, że tabele liczb są nieocenione . Nie bardzo rozumiem dlaczego. Oto tabela liczb:
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
Uzasadnieniem dla posta na blogu jest:
Tabele liczb są naprawdę nieocenione. Używam ich cały czas do manipulacji ciągami, symulacji funkcji okna, zapełniania tabel testowych dużą ilością danych, eliminacji logiki kursora i wielu innych zadań, które bez nich byłyby niezwykle trudne.
Ale nie rozumiem dokładnie, jakie są te zastosowania - czy możesz podać kilka przekonujących, konkretnych przykładów, w których „tablica liczb” oszczędza mnóstwo pracy w SQL Server - i dlaczego powinniśmy je mieć?
sql-server
Jeff Atwood
źródło
źródło
Odpowiedzi:
Widziałem wiele zastosowań, kiedy trzeba wyświetlać „brakujące dane”. Na przykład. masz szereg czasowy (na przykład dziennik dostępu) i chcesz pokazać liczbę trafień dziennie w ciągu ostatnich 30 dni (panel kontrolny analizy). Jeśli to zrobisz
select count(...) from ... group by day
, będziesz liczyć za każdy dzień, ale wynik będzie miał tylko wiersz dla każdego dnia, w którym faktycznie miałeś co najmniej jeden dostęp. Z drugiej strony, jeśli najpierw rzutujesz tabelę dni ze swojej tabeli liczb (select dateadd(day, -number, today) as day from numbers
), a następnie opuściłeś łączenie z liczbami (lub aplikacją zewnętrzną, cokolwiek ci się podoba), otrzymasz wynik, który ma 0 dla liczby dni nie miał dostępu. To tylko przykład. Oczywiście można argumentować, że warstwa prezentacji na desce rozdzielczej poradzi sobie z brakującymi dniami i po prostu pokaże 0, ale niektóre narzędzia (np. SSRS) po prostu nie będą w stanie sobie z tym poradzić.Inne przykłady, które widziałem, wykorzystywały podobne triki szeregów czasowych (data / godzina +/- liczba) do wykonywania wszelkiego rodzaju obliczeń w oknie. Ogólnie rzecz biorąc, ilekroć w imperatywnym języku użyłbyś pętli for ze znaną liczbą iteracji, deklaratywna i ustawiona natura SQL może użyć sztuczki opartej na tabeli liczb.
BTW, odczuwam potrzebę zwrócenia uwagi na fakt, że chociaż przy użyciu tabeli liczb wydaje się to bezwzględnie konieczne do wykonania procedury, nie popadaj w błąd, zakładając, że jest to konieczne. Podam przykład:
Ten program wyświetli 999999, co jest prawie całkowicie gwarantowane.
Spróbujmy to samo w SQL Server, używając tabeli liczb. Najpierw utwórz tabelę zawierającą 1 000 000 liczb:
Teraz zróbmy „pętlę for”:
Wynik to:
Jeśli masz teraz moment WTF (w końcu
number
to klastrowany klucz podstawowy!), Sztuczka nazywa się skanowaniem kolejności alokacji, a ja nie wstawiłem@j*1000+@i
przypadkowo ... Mógłbyś również zaryzykować i powiedzieć, że wynik jest taki, ponieważ równoległość, która czasem może być poprawną odpowiedzią.Pod tym mostem jest wiele trolli i wspomniałem o niektórych w zwarciu operatora logicznego On SQL Server, a funkcje T-SQL nie oznaczają określonej kolejności wykonywania
źródło
Znalazłem tabelę liczb całkiem przydatną w różnych sytuacjach.
W Dlaczego warto rozważyć użycie tabeli liczb pomocniczych? , napisany w 2004 roku, pokazuję kilka przykładów:
W Złe nawyki, aby kopać: używając pętli do zapełniania dużych tabel , pokazuję, jak można wykorzystać tabelę liczb, aby w krótkim czasie wstawiać wiele wierszy (w przeciwieństwie do kolanowego podejścia przy użyciu pętli while).
Podczas przetwarzania listy liczb całkowitych: moje podejście i Więcej na temat dzielenia list: niestandardowe ograniczniki, zapobieganie duplikacjom i utrzymywanie porządku , pokazuję, jak używać tabeli liczb do dzielenia łańcucha (np. Zestawu wartości oddzielonych przecinkami) i zapewnienia wydajności porównania tej i innych metod. Więcej informacji na temat dzielenia i innych operacji na łańcuchach:
I SQL Server tabeli numerów, Poradnik - Część 1 , daję jakieś tło na temat koncepcji i mieć w przyszłości stanowisk w sklepie do konkretnych zastosowań szczegółów.
Istnieje wiele innych zastosowań, to tylko kilka, które wyróżniły się na tyle, że mogłem o nich napisać.
I podobnie jak @ gbn, mam kilka odpowiedzi na temat przepełnienia stosu i na tej stronie, które również używają tabeli liczb.
Na koniec mam serię postów na blogu o generowaniu zestawów bez zapętlania się, które częściowo pokazują przewagę wydajności wynikającą z używania tabeli liczb w porównaniu z większością innych metod (pomijając dziwne wartości odstające Remusa):
źródło
Oto świetny przykład, którego ostatnio użyłem od Adama Machanica:
Użyłem czegoś innego podobnego do a,
CTE
aby znaleźć konkretną instancję podłańcucha (tj. „Znajdź trzecią potok w tym ciągu”) do pracy z skorelowanymi danymi rozdzielonymi:Jeśli nie masz tabeli liczb, alternatywą jest użycie pętli. Zasadniczo tabela liczb pozwala wykonywać iteracje oparte na zestawie, bez kursorów i pętli.
źródło
Używałbym tabeli liczb, ilekroć potrzebuję równoważnika SQL Enumerable.Range. Na przykład użyłem go w odpowiedzi na tej stronie: obliczając liczbę permutacji
źródło