Генерация случайных строк с T-SQL

Вы можете использовать метод .rolling_apply(…) :

diffs_a = pd.rolling_apply(df['count_a'], 2, lambda x: x[0] - x[1])

Альтернативно, если это проще, вы можете напрямую работать с массивами:

count_a_vals = df['count_a'].values
diffs_a = count_a_vals[:-1] - count_a_vals[1:]

82
задан Scott Lawrence 24 August 2009 в 18:52
поделиться

6 ответов

При генерации случайных данных, специально для тестирования, очень полезно сделать данные случайными, но воспроизводимыми. Секрет заключается в том, чтобы использовать явные начальные числа для случайной функции, чтобы при повторном запуске теста с тем же начальным значением он снова производил точно такие же строки. Вот упрощенный пример функции, которая генерирует имена объектов воспроизводимым образом:

alter procedure usp_generateIdentifier
    @minLen int = 1
    , @maxLen int = 256
    , @seed int output
    , @string varchar(8000) output
as
begin
    set nocount on;
    declare @length int;
    declare @alpha varchar(8000)
        , @digit varchar(8000)
        , @specials varchar(8000)
        , @first varchar(8000)
    declare @step bigint = rand(@seed) * 2147483647;

    select @alpha = 'qwertyuiopasdfghjklzxcvbnm'
        , @digit = '1234567890'
        , @specials = '_@# '
    select @first = @alpha + '_@';

    set  @seed = (rand((@seed+@step)%2147483647)*2147483647);

    select @length = @minLen + rand(@seed) * (@maxLen-@minLen)
        , @seed = (rand((@seed+@step)%2147483647)*2147483647);

    declare @dice int;
    select @dice = rand(@seed) * len(@first),
        @seed = (rand((@seed+@step)%2147483647)*2147483647);
    select @string = substring(@first, @dice, 1);

    while 0 < @length 
    begin
        select @dice = rand(@seed) * 100
            , @seed = (rand((@seed+@step)%2147483647)*2147483647);
        if (@dice < 10) -- 10% special chars
        begin
            select @dice = rand(@seed) * len(@specials)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);
            select @string = @string + substring(@specials, @dice, 1);
        end
        else if (@dice < 10+10) -- 10% digits
        begin
            select @dice = rand(@seed) * len(@digit)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);
            select @string = @string + substring(@digit, @dice, 1);
        end
        else -- rest 80% alpha
        begin
            declare @preseed int = @seed;
            select @dice = rand(@seed) * len(@alpha)+1
                , @seed = (rand((@seed+@step)%2147483647)*2147483647);

            select @string = @string + substring(@alpha, @dice, 1);
        end

        select @length = @length - 1;   
    end
end
go

При запуске тестов вызывающая сторона генерирует случайное начальное число, которое ассоциируется с тестовым запуском (сохраняет его в таблице результатов), а затем передает начальное значение , похожее на это:

declare @seed int;
declare @string varchar(256);

select @seed = 1234; -- saved start seed

exec usp_generateIdentifier 
    @seed = @seed output
    , @string = @string output;
print @string;  
exec usp_generateIdentifier 
    @seed = @seed output
    , @string = @string output;
print @string;  
exec usp_generateIdentifier 
    @seed = @seed output
    , @string = @string output;
print @string;  

Обновление 2016-02-17: См. комментарии ниже, у исходной процедуры была проблема в том, как она продвигала случайное начальное число. Я обновил код, а также устранил упомянутую проблему «раз за разом».

35
ответ дан 24 November 2019 в 08:07
поделиться

Это произведет строку, которую 96 символов в длине, от диапазона Base64 (uppers, понижает, числа, + и/). Добавление 3 "NEWID ()" увеличит длину на 32 без дополнения Base64 (=).

    SELECT 
        CAST(
            CONVERT(NVARCHAR(MAX),
                CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
                +CONVERT(VARBINARY(8), NEWID())
            ,2) 
        AS XML).value('xs:base64Binary(xs:hexBinary(.))', 'VARCHAR(MAX)') AS StringValue

при применении этого к набору удостоверьтесь, что представили что-то от того набора так, чтобы NEWID () был повторно вычислен, иначе Вы получите то же значение каждый раз:

  SELECT 
    U.UserName
    , LEFT(PseudoRandom.StringValue, LEN(U.Pwd)) AS FauxPwd
  FROM Users U
    CROSS APPLY (
        SELECT 
            CAST(
                CONVERT(NVARCHAR(MAX),
                    CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), NEWID())
                    +CONVERT(VARBINARY(8), U.UserID)  -- Causes a recomute of all NEWID() calls
                ,2) 
            AS XML).value('xs:base64Binary(xs:hexBinary(.))', 'VARCHAR(MAX)') AS StringValue
    ) PseudoRandom
0
ответ дан 24 November 2019 в 08:07
поделиться

Я сделал это в SQL 2000, создав таблицу, в которой были символы, которые я хотел использовать, создав представление, которое выбирает символы из этой таблицы, упорядочивая их с помощью newid (), а затем выбрав верхний 1 символ из этого представления .

CREATE VIEW dbo.vwCodeCharRandom
AS
SELECT TOP 100 PERCENT 
    CodeChar
FROM dbo.tblCharacter
ORDER BY 
    NEWID()

...

SELECT TOP 1 CodeChar FROM dbo.vwCodeCharRandom

Затем вы можете просто вытащить символы из представления и объединить их по мере необходимости.

РЕДАКТИРОВАТЬ: Вдохновленный ответом Стефана ...

select top 1 RandomChar from tblRandomCharacters order by newid()

Нет необходимости в представлении (на самом деле я не уверен, почему я это сделал - код написан несколько лет назад). Вы по-прежнему можете указать символы, которые хотите использовать в таблице.

0
ответ дан 24 November 2019 в 08:07
поделиться

Сначала я наткнулся на это сообщение в блоге , затем я обнаружил следующие сохраненные Для этого я использую процедуру, которую я использую в текущем проекте (извините за странное форматирование):

CREATE PROCEDURE [dbo].[SpGenerateRandomString]
@sLength tinyint = 10,
@randomString varchar(50) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @counter tinyint
DECLARE @nextChar char(1)
SET @counter = 1
SET @randomString = ”

WHILE @counter <= @sLength
BEGIN
SELECT @nextChar = CHAR(48 + CONVERT(INT, (122-48+1)*RAND()))

IF ASCII(@nextChar) not in (58,59,60,61,62,63,64,91,92,93,94,95,96)
BEGIN
SELECT @randomString = @randomString + @nextChar
SET @counter = @counter + 1
END
END
END
0
ответ дан 24 November 2019 в 08:07
поделиться

Подобно первому примеру, но с большей гибкостью:

-- min_length = 8, max_length = 12
SET @Length = RAND() * 5 + 8
-- SET @Length = RAND() * (max_length - min_length + 1) + min_length

-- define allowable character explicitly - easy to read this way an easy to 
-- omit easily confused chars like l (ell) and 1 (one) or 0 (zero) and O (oh)
SET @CharPool = 
    'abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789.,-_!$@#%^&*'
SET @PoolLength = Len(@CharPool)

SET @LoopCount = 0
SET @RandomString = ''

WHILE (@LoopCount < @Length) BEGIN
    SELECT @RandomString = @RandomString + 
        SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength), 1)
    SELECT @LoopCount = @LoopCount + 1
END

Я забыл упомянуть одну из других функций, которые делают это более гибким. Повторяя блоки символов в @CharPool, вы можете увеличить вес определенных символов, чтобы они с большей вероятностью были выбраны.

47
ответ дан 24 November 2019 в 08:07
поделиться

Использование гида

SELECT @randomString = CONVERT(varchar(255), NEWID())

очень короткое ...

180
ответ дан 24 November 2019 в 08:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: