Наш постоянный эксперт по базам данных говорит нам, что таблицы чисел бесценны . Я не совсем понимаю, почему. Вот таблица чисел:
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
Согласно сообщению в блоге, обоснование
Таблицы чисел действительно бесценны. Я использую их все время для работы со строками, имитации оконных функций, заполнения тестовых таблиц большим количеством данных, устранения логики курсора и многих других задач, которые без них были бы невероятно трудными.
Но я не совсем понимаю, что это за использование - можете ли вы привести некоторые убедительные, конкретные примеры того, как «таблица чисел» экономит вам массу работы в SQL Server - и почему мы должны их иметь?
sql-server
Джефф Этвуд
источник
источник
Ответы:
Я видел много случаев, когда вам нужно проецировать «недостающие данные». Например. у вас есть временной ряд (например, журнал доступа), и вы хотите показать количество посещений в день за последние 30 дней (панель инструментов аналитики). Если вы сделаете a,
select count(...) from ... group by day
вы получите счет за каждый день, но результат будет содержать только строку за каждый день, когда у вас был хотя бы один доступ. С другой стороны, если вы сначала проецируете таблицу дней из таблицы чисел (select dateadd(day, -number, today) as day from numbers
), а затем оставляете объединение со счетчиками (или внешним применением, как вам нравится), то вы получите результат с 0 для количества дней, которые вы не было доступа. Это только один пример. Конечно, можно утверждать, что уровень представления вашей информационной панели может обрабатывать пропущенные дни и просто отображать 0, но некоторые инструменты (например, SSRS) просто не смогут справиться с этим.Другие примеры, которые я видел, использовали аналогичные трюки с временными рядами (дата / время +/- число) для выполнения всех видов оконных вычислений. В общем, всякий раз, когда в императивном языке вы используете цикл for с хорошо известным числом итераций, декларативный и заданный характер SQL может использовать прием, основанный на таблице чисел.
Кстати, я чувствую необходимость подчеркнуть тот факт, что даже при использовании таблицы чисел это выглядит как императивное процедурное исполнение, не впадайте в заблуждение, полагая, что это обязательно. Позвольте мне привести пример:
Эта программа выдаст 999999, что в значительной степени гарантировано.
Давайте попробуем то же самое в SQL Server, используя таблицу чисел. Сначала создайте таблицу из 1 000 000 номеров:
Теперь давайте сделаем цикл for:
Результат:
Если у вас сейчас есть момент WTF (в конце концов,
number
это кластерный первичный ключ!), Этот трюк называется сканированием порядка распределения, и я не вставил@j*1000+@i
его случайно ... Вы могли бы также рискнуть и сказать, что результат состоит в том, что параллелизм и это иногда может быть правильным ответом.Под этим мостом много троллей, и я упомянул некоторые из них в « Булевых операторах на SQL Server», и функции T-SQL не предполагают определенного порядка выполнения.
источник
Я нашел таблицу чисел весьма полезной в различных ситуациях.
На Почему следует использовать вспомогательную таблицу чисел? , написанный в 2004 году, я покажу несколько примеров:
В разделе «Плохие привычки»: используя циклы для заполнения больших таблиц , я показываю, как можно использовать таблицу чисел для быстрой вставки большого количества строк (в отличие от подхода коленного рефлекса с использованием цикла while).
В разделе «Обработка списка целых чисел: мой подход» и « Подробнее о разделении списков: настраиваемые разделители, предотвращение дублирования и поддержание порядка» я показываю, как использовать таблицу чисел для разделения строки (например, набора значений, разделенных запятыми) и обеспечения производительности. Сравнение между этим и другими методами. Больше информации о разделении и обработке других строк:
И в Таблице чисел SQL Server, объяснение - часть 1 , я даю некоторое представление о концепции и будущие публикации в запасе, чтобы детализировать конкретные приложения.
Есть много других применений, это лишь некоторые из них, которые выделены мне достаточно, чтобы написать о них.
И, как и @gbn, у меня есть несколько ответов о переполнении стека и на этом сайте, которые также используют таблицу чисел.
Наконец, у меня есть серия постов в блоге о создании наборов без зацикливания, которые частично показывают преимущество в производительности при использовании таблицы чисел по сравнению с большинством других методов (за исключением странного выброса Ремуса):
источник
Вот прекрасный пример, который я недавно использовал от Адама Мачаника:
Я использовал нечто похожее с a,
CTE
чтобы найти конкретный экземпляр подстроки (например, «Найти 3-й канал в этой строке») для работы с коррелированными данными с разделителями:Если у вас нет таблицы чисел, альтернативой является использование некоторого цикла. По сути, таблица чисел позволяет выполнять итерации на основе множеств без курсоров и циклов.
источник
Я бы использовал таблицу чисел всякий раз, когда мне нужен SQL-эквивалент Enumerable.Range. Например, я только использовал это в ответе на этом сайте: вычисление количества перестановок
источник