Недавно мне было дано задание напечатать все простые числа (1-100). Я там сильно провалился. Мой код:
Create Procedure PrintPrimeNumbers
@startnum int,
@endnum int
AS
BEGIN
Declare @a INT;
Declare @i INT = 1
(
Select a = @startnum / 2;
WHILE @i<@a
BEGIN
@startnum%(@a-@i)
i=i+1;
)
END
Хотя я закончил так и не завершив его, мне интересно, возможно ли делать такие программы в базе данных (SQL Server 2008 R2).
Если да, то чем это может закончиться.
sql-server
sql-server-2008-r2
t-sql
IsPostBack
источник
источник
Ответы:
Безусловно, самый быстрый и простой способ вывести «все простые числа (1-100)» - это полностью принять тот факт, что простые числа являются известным, конечным и неизменным набором значений («известных» и «конечных» в пределах конкретный ассортимент, конечно). При таком небольшом масштабе зачем каждый раз тратить ЦП на вычисление набора значений, которые были известны очень давно, и почти не занимать память для хранения?
Конечно, если вам нужно вычислить простые числа от 1 до 100, следующее довольно эффективно:
Этот запрос проверяет только нечетные числа, так как четные числа в любом случае не будут простыми. Это также характерно для диапазона от 1 до 100.
Теперь, если вам нужен динамический диапазон (аналогичный тому, который показан в примере кода в вопросе), то приведенная ниже адаптация приведенного выше запроса все еще довольно эффективна (он рассчитал диапазон 1 - 100 000 - 9592 записи - менее чем за 1 секунду):
Мое тестирование (использование
SET STATISTICS TIME, IO ON;
) показывает, что этот запрос работает лучше, чем два других ответа (пока):ДИАПАЗОН: 1 - 100
ДИАПАЗОН: 1 - 10000
ДИАПАЗОН: 1 - 100 000
ДИАПАЗОН: 99 900 - 100 000
ПРИМЕЧАНИЕ . Чтобы выполнить этот тест, мне пришлось исправить ошибку в коде Дэна -
@startnum
он не был включен в запрос, поэтому он всегда начинался с1
. Я заменилDividend.num <= @endnum
строку сDividend.num BETWEEN @startnum AND @endnum
.ДИАПАЗОН: 1 - 100 000 (частичный повторный тест)
После исправления запроса Дэна для теста 99 900 - 100 000 я заметил, что в списке больше нет логических операций чтения. Поэтому я повторно протестировал этот диапазон с примененным исправлением и обнаружил, что логические чтения снова исчезли, и времена были немного лучше (и да, было возвращено то же количество строк).
источник
ROW_NUMBER() OVER (ORDER BY (SELECT 1))
? НеROW_NUMBER() OVER ()
будет эквивалентным?OVER ()
, вы получите следующее сообщение об ошибке:The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.
. И, сORDER BY
, это не может быть константой, следовательно, подзапрос для возврата константы.DECLARE @RangeStart INT = 999900, @RangeEnd INT = 1000000;
это работает, но как только я установилDECLARE @RangeStart INT = 9999999900, @RangeEnd INT = 10000000000;
это говоритMsg 8115, Level 16, State 2, Line 1 Arithmetic overflow error converting expression to data type int. Msg 1014, Level 15, State 1, Line 5 A TOP or FETCH clause contains an invalid value.
?INT
. Максимальное значение, котороеINT
может храниться, составляет 2 147 483 647, что меньше вашего начального значения 9 999 999 900. Вы получаете эту ошибку, даже если вы выполняете толькоDECLARE
. Вы можете попробовать изменить типы данных переменныхBIGINT
и посмотреть, как это происходит. Вполне возможно, что для поддержки этого потребуются другие незначительные изменения. Для диапазонов типов данных, пожалуйста, смотрите: int, bigint, smallint и tinyint .Простой, но не очень эффективный способ вернуть простые числа в диапазоне 2-100 (1 не простое) будет
Вы также можете материализовать числа 2-100 в таблице и внедрить Сито Эратосфена через повторные обновления или удаления.
источник
Да, это возможно, но я не думаю, что T-SQL является подходящим инструментом для этой работы. Ниже приведен пример подхода на основе множеств в T-SQL для этой проблемы.
источник
Мы можем написать код ниже, и он работает:
Выше я создал хранимую процедуру для получения простых чисел.
Чтобы узнать результаты, выполните хранимую процедуру:
источник
источник