У меня есть два числа в качестве ввода от пользователя, например, 1000
и 1050
.
Как мне сгенерировать числа между этими двумя числами, используя SQL-запрос, в отдельных строках? Я хочу этот:
1000
1001
1002
1003
.
.
1050
sql
sql-server
tsql
sql-server-2008
user3211705
источник
источник
альтернативным решением является рекурсивный CTE:
источник
Demo
Обратите внимание, что в этой таблице максимум 2048, потому что в числах есть пробелы.
Вот немного лучший подход с использованием системного представления (начиная с SQL-Server 2005):
Demo
или используйте пользовательскую таблицу номеров. Благодарности Аарону Бертрану, я предлагаю прочитать всю статью: создать набор или последовательность без циклов
источник
WHERE type = 'P'
и избежатьSELECT DISTINCT
String index out of range: 33
Я недавно написал эту встроенную табличную функцию, чтобы решить эту проблему. Он не ограничен в диапазоне, кроме памяти и памяти. Он не обращается к таблицам, поэтому нет необходимости в чтении или записи на диск в целом. Он добавляет значения соединений экспоненциально на каждой итерации, поэтому он очень быстр даже для очень больших диапазонов. Он создает десять миллионов записей за пять секунд на моем сервере. Это также работает с отрицательными значениями.
Это удобно для диапазонов дат и времени:
Вы можете использовать перекрестное соединение, чтобы разделить записи на основе значений в таблице. Так, например, чтобы создать запись для каждой минуты в диапазоне времени в таблице, вы можете сделать что-то вроде:
источник
SELECT X FROM fn_ConsecutiveNumbers(5, 500) ORDER BY X;
Лучший вариант, который я использовал, выглядит следующим образом:
Я создал миллионы записей, используя это, и это прекрасно работает.
источник
Это работает для меня!
источник
sys.all_objects
- для небольших диапазонов <2000 пунктов, это не проблема. Не уверен, что у него будут проблемы с разрешениями? идеально подходит для быстрой генерации пакета тестовых данных.select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount from sys.all_objects a, sys.all_objects b
, Там, где раньше я мог генерировать только 2384 строки, теперь я могу создать 5683456 строк.Лучший способ - использовать рекурсивные ctes.
Saludos.
источник
источник
Если у вас нет проблем с установкой сборки CLR на вашем сервере, хорошим вариантом будет написание табличной функции в .NET. Таким образом, вы можете использовать простой синтаксис, облегчая объединение с другими запросами и в качестве бонуса не будет тратить память, поскольку результат передается в потоковом режиме.
Создайте проект, содержащий следующий класс:
Поместите сборку где-нибудь на сервере и запустите:
Теперь вы можете запустить:
источник
Ничего нового, но я переписал решение Брайана Пресслера так, чтобы оно было проще для глаз, оно может быть полезно кому-то (даже если это только будущее для меня):
источник
ROW_NUMBER()
не имеют этой проблемы.2 года спустя, но я обнаружил, что у меня была такая же проблема. Вот как я это решил. (отредактировано для включения параметров)
источник
Ответ slartidan может быть улучшен с точки зрения производительности, исключив все ссылки на декартово произведение и используя
ROW_NUMBER()
вместо этого ( сравнительный план выполнения ):Оберните его внутри CTE и добавьте предложение where, чтобы выбрать нужные числа:
источник
SELECT ROW_NUMBER() OVER (...) - 1 AS n
. В некоторых случаях это может снизить производительность.Вот пара вполне оптимальных и совместимых решений:
источник
select
INGwhere spt_values.number between @min and @max
?Я знаю, что я опоздал на 4 года, но я наткнулся на еще один альтернативный ответ на эту проблему. Проблема скорости заключается не только в предварительной фильтрации, но и в предотвращении сортировки. Можно заставить ордер на объединение выполнить таким образом, чтобы декартово произведение фактически считало результат объединения. Используя ответ Слартидана в качестве отправной точки:
Если мы знаем диапазон, который хотим, мы можем указать его через @Upper и @Lower. Комбинируя подсказку соединения REMOTE и TOP, мы можем вычислить только то подмножество значений, которое нам нужно, без потерь.
Подсказка по удалению REMOTE заставляет оптимизатор сравнивать сначала с правой стороны соединения. Указав каждое соединение как УДАЛЕННОЕ от самого значительного до наименее значимого значения, само соединение будет считаться вверх на единицу правильно. Нет необходимости фильтровать с помощью WHERE или сортировать с помощью ORDER BY.
Если вы хотите увеличить диапазон, вы можете продолжать добавлять дополнительные объединения с прогрессивно более высокими порядками величины, если они упорядочены от наиболее значимых до наименее значимых в предложении FROM.
Обратите внимание, что это запрос, специфичный для SQL Server 2008 или выше.
источник
Это также будет делать
источник
Лучшая скорость при выполнении запроса
источник
рекурсивный CTE в экспоненциальном размере (даже для 100 рекурсий по умолчанию это может составить до 2 ^ 100 чисел):
источник
@startnum
иendnum
должен быть введен пользователем?Мне пришлось вставить файл filepath в базу данных, используя аналогичный метод. Запрос ниже работал нормально:
Код для вас будет:
источник
Это то, что я делаю, это довольно быстро и гибко, и не много кода.
Обратите внимание, что (ORDER BY @count) - пустышка. Он ничего не делает, но ROW_NUMBER () требует ORDER BY.
Изменить : я понял, что первоначальный вопрос должен был получить диапазон от х до у. Мой скрипт может быть изменен так, чтобы получить диапазон:
источник
источник
Это работает только для последовательностей, если в некоторых таблицах приложений есть строки. Предположим, мне нужна последовательность из 1..100, и у меня есть таблица приложения dbo.foo со столбцом (числового или строкового типа) foo.bar:
Несмотря на то, что dbo.foo.bar присутствует в предложении order by, он не должен иметь отдельных или даже ненулевых значений.
Конечно, SQL Server 2012 имеет объекты последовательности, поэтому в этом продукте есть естественное решение.
источник
Вот что я придумал:
Генерирует до 2 ^ 24 значений. Условия соединения сохраняют скорость для небольших значений.
источник
Для меня это завершилось за 36 секунд на нашем сервере DEV. Как и ответ Брайана, в запросе важно сосредоточиться на фильтрации по диапазону; BETWEEN все еще пытается сгенерировать все начальные записи до нижней границы, даже если они не нужны.
Обратите внимание, что ROW_NUMBER - это bigint , поэтому мы не можем просмотреть 2 ^ ^ 64 (== 16 ^^ 16) сгенерированных записей любым методом, который его использует. Поэтому этот запрос учитывает тот же верхний предел для сгенерированных значений.
источник
Это использует процедурный код и табличную функцию. Медленно, но легко и предсказуемо.
Использование:
Это таблица, поэтому вы можете использовать ее в соединениях с другими данными. Я чаще всего использую эту функцию в качестве левой части объединения против часа, дня и т. Д. GROUP BY, чтобы обеспечить непрерывную последовательность значений времени.
Производительность скучная (16 секунд на миллион строк), но достаточная для многих целей.
источник
Oracle 12c; Быстро, но ограничено:
Примечание : ограничено количеством строк представления all_objects;
источник
Решение, которое я разработал и использовал в течение довольно долгого времени (некоторые используют общие работы других), немного похоже на хотя бы одно опубликованное. Он не ссылается ни на какие таблицы и возвращает несортированный диапазон до 1048576 значений (2 ^ 20) и может включать отрицательные значения при желании. Вы можете, конечно, отсортировать результат, если это необходимо. Он работает довольно быстро, особенно на небольших диапазонах.
источник
источник
Я сделал ниже функцию после прочтения этой темы. Просто и быстро:
источник