How to create random number for ID field In SQL Server? - sql

How to create random number for an ID field In SQL Server?
I want to create random number betwen 1000 to 9999.
How to create this structure?

RAND is a built in function. It should meet your needs. This should give you the desired results: select cast(rand() * 8999 + 1000 as int)
http://msdn.microsoft.com/en-us/library/ms177610%28v=SQL.105%29.aspx

You've not mention whether you want random number generated as unique non-repetitive.
DECLARE #Random INT;
DECLARE #Upper INT;
DECLARE #Lower INT;
---- This will create a random number between 1 and 999
SET #Lower = 1000 ---- The lowest random number
SET #Upper = 9999 ---- The highest random number
SELECT #Random = ROUND(((#Upper - #Lower -1) * RAND() + #Lower), 0)
SELECT #Random;
Source

Another method
select number/power(10,len(number)-4) as number from
(
select top 10000 abs(checksum(newid())) as number
from sysobjects s1 cross join sysobjects s2
) as T
Also refer this http://beyondrelational.com/modules/2/blogs/70/posts/10810/generating-random-numbers-part-ii.aspx

Related

Divide two numbers to a range without using parts

I have to divide two numbers based on the increment provided by the users, I found an answer which is based on the parts.
I can not use parts as it effects numbers of rows in result, rather I have to pass increment.
Here is my query using parts.
declare #min numeric(18,0)
declare #max numeric(18,0)
declare #parts numeric(18,0)
select #min = 100 ,
#max = 204,
#parts = 10
declare #increment int = (#max - #min) / #parts
while #max >= #min
begin
declare #newMin numeric(18,0) = #min + #increment
print convert(varchar, #min) + ' - ' + convert(varchar, #newMin) select #min = #newMin + 1
end
Expected output, as you can see in the query my input is min and max with parts based on which the increments are calculating but I have to fix increment like 10 or 100.
From To
--------
100 110
111 121
122 132
133 143
144 154
155 165
166 176
177 187
188 198
199 204
There are 2 answers here, 1 based on the original version of the question (where To could be larger than #max) and that your goal is that #parts is the value of numbers in you want in the bucket (+1). The latter is that you want to split the range into that many buckets, and the last bucket is shrunk if the upper value is larger than the #max value. Both use a Tally function here, which I include the definition of:
CREATE FUNCTION [fn].[Tally] (#End bigint, #StartAtOne bit)
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT 0 AS I
WHERE #StartAtOne = 0
UNION ALL
SELECT TOP (#End)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3, N N4, N N5, N N6, N N7, N N8)
SELECT I
FROM Tally;
GO
DECLARE #min numeric(18,0) = 100,
#max numeric(18,0) = 304,
#parts numeric(18,0) = 10;
SELECT #min + (T.I * (#parts+1)),
#min + ((T.I+1) * (#parts+1))-1
FROM fn.Tally((#max - #min)/(#parts+1),0) T;
SELECT #min + (T.I * CEILING(((#max - #min)/#parts))),
CASE WHEN #min + ((T.I+1)* CEILING(((#max - #min)/#parts)))-1 > #max THEN #max ELSE #min + ((T.I+1)* CEILING(((#max - #min)/#parts)))-1 END
FROM fn.Tally(#parts-1,0) T
db<>fiddle
The question is unclear and doesn't describe the actual problem that needs solving. The code shows a way to partition a continuous range of numbers 100-204 into N partitions, in this case specified by #parts. It's not very efficient but it works.
Partitioning a range into parts is a popular SQL puzzle so there are a lot of articles over the past 30-40 years that show how to do it for different databases, using different features and trying to get the best performance. In the simple form there are two ways to partition :
By part count, what you have
By part size
If you don't want by part count, you probably want by part size. Doing this isn't complicated either and doesn't require slow loops.
Assuming we have a Tally table named Numbers, with all numbers up to eg 1M, the query to partition a range would be :
declare #start int=100
declare #end int=204
declare #size int=25
;with parts as (
select Number,(Number-#start)/#size as part_id
from numbers where number between #start and #end
)
select part_id,min(number) as [Start],max(number) as [End]
from parts
group by part_id
----------------------
part_id Start End
0 100 124
1 125 149
2 150 174
3 175 199
4 200 204
First, the Number is divided by the size we want using integer division to determine the part it belongs to. The results are then grouped by the Part ID and the range limits are the minimum and maximum Number in that group.
Creating a Numbers table is cheap. I used this script to generate a table with 1M numbers which takes about 11MB only:
DECLARE #UpperBound INT = 1000000;
;WITH cteN(Number) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id]) - 1
FROM sys.all_columns AS s1
CROSS JOIN sys.all_columns AS s2
)
SELECT [Number] INTO dbo.Numbers
FROM cteN WHERE [Number] <= #UpperBound;
CREATE UNIQUE CLUSTERED INDEX CIX_Number ON dbo.Numbers([Number])
WITH
(
FILLFACTOR = 100,
DATA_COMPRESSION = ROW
);
Data compression is available in all SQL Server versions and editions since SQL Server 2016 SP1.
The same technique can be used to partition a range into N parts, using the NTILE function this time :
declare #parts int=10
;with parts as (
select number, NTILE(#parts) over(order by number) as part_id
from numbers where number between #start and #end
)
select part_id,min(number) as [Start],max(number) as [End]
from parts
group by part_id
In real business cases NTILE is used to partition results into "buckets"

Populate all columns with random int

I'm trying to populate 3 columns all rows with some random ints.
The code below has an error
Incorrect syntax near "#Upper. Expecting ( or Select
What am I doing wrong?
---- Create the variables for the random number generation
DECLARE #Random INT;
DECLARE #Upper INT;
DECLARE #Lower INT
---- Create a random number between 1 and 111
SET #Lower = 1 -- The lowest random number
SET #Upper = 111 -- The highest random number
UPDATE [tblProject]
SET
[ContractorID1] = #Random = ROUND(((#Upper - #Lower -1) * RAND() + #Lower), 0) -- error
,[ContractorID2] = #Random = ROUND(((#Upper - #Lower -1) * RAND() + #Lower), 0) -- error
,[ContractorID3] = #Random = ROUND(((#Upper - #Lower -1) * RAND() + #Lower), 0) -- error
Take out the "#Random = " in your update statement. It doesn't serve any purpose. You aren't using that variable at all, so you have no need to even declare it. Just do direct assignment.
And as you've discovered, the RAND() function will return the same value for the same row. If you need something different, there are other solutions.

SQL Server update with random values

I want to update a table generating random "pin" numbers. This is what I'm trying but in the end all the rows are getting the same number. I have tried doing it in a while cycle but it is still the same.
BEGIN TRAN
DECLARE #Random INT;
DECLARE #Upper INT;
DECLARE #Lower INT
---- This will create a random number between 10000 and 99999
SET #Lower = 10000 ---- The lowest random number
SET #Upper = 99999 ---- The highest random number
UPDATE Totals
SET Pin = ROUND(((#Upper - #Lower -1) * RAND() + #Lower), 0)
--check for repeated numbers
SELECT
Pin, COUNT(*)
FROM
Totals
GROUP BY
Pin
HAVING
COUNT(*) > 1
--commit
--rollback
Thanks for your help
You can use CRYPT_GEN_RANDOM() instead of RAND() to get around RAND() being evaluated once:
UPDATE totals
SET pin = (#Lower + ABS(CRYPT_GEN_RANDOM(8) % (#Upper-#Lower+1)))
rand() is evaluated once per query.
WITH toupdate as (
SELECT t.*,
ROUND(((#Upper - #Lower -1) * RAND(CHECKSUM(NEWID())) + #Lower), 0) as new_Pin
FROM Totals
)
UPDATE Totals
SET Pin = new_Pin;
One way around this is to use RAND(CHECKSUM(NEWID())). However, you still have to be careful about expressions and subqueries being optimized to run only once. I think the above formulation should work.

How do I get nth number of records from 100 records by select query in SQL Server?

I want to select nth record randomly from 100 of records by using select query in SQL Server
Here is a one-query solution:
select top 1 t.*
from table t
order by newid();
In the below code #R produces the random number and it is used by the CTE to pick the random row.
DECLARE #Upper INT;
DECLARE #Lower INT;
SET #Lower = 1
SET #Upper = 100
DECLARE #R INT = (SELECT #Lower + CONVERT(INT, (#Upper-#Lower+1)*RAND()))
;WITH myTableWithRows AS (
SELECT (ROW_NUMBER() OVER (ORDER BY myTable.SomeField)) as row,*
FROM myTable)
SELECT * FROM myTableWithRows WHERE row = #R

Generate random int value from 3 to 6

Is it possible in Microsoft SQL Server generate random int value from Min to Max (3-9 example, 15-99 e.t.c)
I know, I can generate from 0 to Max, but how to increase Min border?
This query generate random value from 1 to 6. Need to change it from 3 to 6.
SELECT table_name, 1.0 + floor(6 * RAND(convert(varbinary, newid()))) magic_number
FROM information_schema.tables
Added 5 sec later:
SELECT table_name, 3.0 + floor(4 * RAND(convert(varbinary, newid()))) magic_number
FROM information_schema.tables
A helpful editor added the 'Select' before each statement but the point of this item is that it can generate unique keys for each row in a return, not just one item (For that I would us the Rand() function).
For example:
Select top 100 Rand(),* from tblExample
Would return the same random value for all 100 rows.
While:
Select top 100 ABS(CHECKSUM(NEWID()) % 10),* from tblexample
Would return a different random value between 0 and 9 on each row in the return.
So while the select makes it easier to copy and paste, you can copy the logic into a select statement if that is what is required.
This generates a random number between 0-9
SELECT ABS(CHECKSUM(NEWID()) % 10)
1 through 6
SELECT ABS(CHECKSUM(NEWID()) % 6) + 1
3 through 6
SELECT ABS(CHECKSUM(NEWID()) % 4) + 3
Dynamic (Based on Eilert Hjelmeseths Comment - thanks to jiraiya for providing the visual presentation)
SELECT ABS(CHECKSUM(NEWID()) % (#max - #min + 1)) + #min
Updated based on comments:
NEWID generates random string (for each row in return)
CHECKSUM takes value of string and creates number
modulus (%) divides by that number and returns the remainder (meaning max value is one less than the number you use)
ABS changes negative results to positive
then add one to the result to eliminate 0 results (to simulate a dice roll)
I see you have added an answer to your question in SQL Server 2008 you can also do
SELECT 3 + CRYPT_GEN_RANDOM(1) % 4 /*Random number between 3 and 6*/
FROM ...
A couple of disadvantages of this method are
This is slower than the NEWID() method
Even though it is evaluated once per row the query optimiser does not realise this which can lead to odd results.
but just thought I'd add it as another option.
You can do this:
DECLARE #maxval TINYINT, #minval TINYINT
select #maxval=24,#minval=5
SELECT CAST(((#maxval + 1) - #minval) *
RAND(CHECKSUM(NEWID())) + #minval AS TINYINT)
And that was taken directly from this link, I don't really know how to give proper credit for this answer.
Here is the simple and single line of code
For this use the SQL Inbuild RAND() function.
Here is the formula to generate random number between two number (RETURN INT Range)
Here a is your First Number (Min) and b is the Second Number (Max) in Range
SELECT FLOOR(RAND()*(b-a)+a)
Note: You can use CAST or CONVERT function as well to get INT range number.
( CAST(RAND()*(25-10)+10 AS INT) )
Example:
SELECT FLOOR(RAND()*(25-10)+10);
Here is the formula to generate random number between two number (RETURN DECIMAL Range)
SELECT RAND()*(b-a)+a;
Example:
SELECT RAND()*(25-10)+10;
More details check this: https://www.techonthenet.com/sql_server/functions/rand.php
Simply:
DECLARE #MIN INT=3; --We define minimum value, it can be generated.
DECLARE #MAX INT=6; --We define maximum value, it can be generated.
SELECT #MIN+FLOOR((#MAX-#MIN+1)*RAND(CONVERT(VARBINARY,NEWID()))); --And then this T-SQL snippet generates an integer between minimum and maximum integer values.
You can change and edit this code for your needs.
Nice and simple, from Pinal Dave's site:
http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/
DECLARE #Random INT;
DECLARE #Upper INT;
DECLARE #Lower INT
SET #Lower = 3 ---- The lowest random number
SET #Upper = 7 ---- One more than the highest random number
SELECT #Random = ROUND(((#Upper - #Lower -1) * RAND() + #Lower), 0)
SELECT #Random
(I did make a slight change to the #Upper- to include the upper number, added 1.)
In general:
select rand()*(#upper-#lower)+#lower;
For your question:
select rand()*(6-3)+3;
<=>
select rand()*3+3;
SELECT ROUND((6 - 3 * RAND()), 0)
Lamak's answer as a function:
-- Create RANDBETWEEN function
-- Usage: SELECT dbo.RANDBETWEEN(0,9,RAND(CHECKSUM(NEWID())))
CREATE FUNCTION dbo.RANDBETWEEN(#minval TINYINT, #maxval TINYINT, #random NUMERIC(18,10))
RETURNS TINYINT
AS
BEGIN
RETURN (SELECT CAST(((#maxval + 1) - #minval) * #random + #minval AS TINYINT))
END
GO
DECLARE #min INT = 3;
DECLARE #max INT = 6;
SELECT #min + ROUND(RAND() * (#max - #min), 0);
Step by step
DECLARE #min INT = 3;
DECLARE #max INT = 6;
DECLARE #rand DECIMAL(19,4) = RAND();
DECLARE #difference INT = #max - #min;
DECLARE #chunk INT = ROUND(#rand * #difference, 0);
DECLARE #result INT = #min + #chunk;
SELECT #result;
Note that a user-defined function thus not allow the use of RAND(). A workaround for this (source: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/) is to create a view first.
CREATE VIEW [dbo].[vw_RandomSeed]
AS
SELECT RAND() AS seed
and then create the random function
CREATE FUNCTION udf_RandomNumberBetween
(
#min INT,
#max INT
)
RETURNS INT
AS
BEGIN
RETURN #min + ROUND((SELECT TOP 1 seed FROM vw_RandomSeed) * (#max - #min), 0);
END