81

I have a simple SQL table which has a DateTime column. I would like to update all the rows (>100000 rows) with a random date. Is there a simple way to do this a SQL Query?

Martin
  • 39,309
  • 62
  • 192
  • 278

10 Answers10

102

Use this to generate a smalldatetime between 01 Jan 1900 and 06 Jun 2079 (not checked, SQL not installed)

DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)

NEWID is better then trying to use RAND: RAND does not generate different values row in a single SELECT or UPDATE (well it didn't in SQL 2000, in case behaviour has changed).

Edit: like this

UPDATE
  table
SET
  datetimecol = DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0)

Edit: changed 65535 to 65530 and added ABS to avoid overflow at upper limit of range

gbn
  • 422,506
  • 82
  • 585
  • 676
  • Clever! Worked for me on SQL Server 2000. create table #test (d datetime); insert into #test values(null); insert into #test values(null); insert into #test values(null); update #test SET d = DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0); select * from #test; drop table #test; – Patrick McElhaney Apr 27 '09 at 18:43
  • Please, why number is 65530? How to count it? – Amelina Nov 27 '17 at 18:51
  • @Amelina "changed 65535 to 65530 and added ABS to avoid overflow at upper limit of range" – gbn Nov 28 '17 at 07:34
  • Yeah, I got it. I didn't got how to calculate it for a different range. Is 65530 seconds, milliseconds, or? – Amelina Nov 28 '17 at 07:37
  • 1
    @Amelina those are the maximum amount of days. If you do `select dateadd(day,65530,0)` you will see it ends at 2079-06-01. – Sander Jul 16 '18 at 07:24
71

I will complement the answers below,

SELECT DATEADD(DAY, ABS(CHECKSUM(NEWID()) % 3650), '2000-01-01')
FROM your_table

This generates dates starting from 2000-01-01, and you can change the amount of days in the modulus value, I put 3650 (about 10 years), this approach doesn't overflow.

If you want to update, then

UPDATE your_table
SET your_date_field = DATEADD(DAY, ABS(CHECKSUM(NEWID()) % 3650), '2000-01-01')
WHERE your_conditions
Jhonny D. Cano -Leftware-
  • 17,663
  • 14
  • 81
  • 103
  • 2
    Yes, I had an error in mine. CHECKSUM generates signed 32 bit integers so I added ABS – gbn Apr 27 '09 at 18:41
50

This question seems quite old but my answer might be usefull to others.

      Update table
      SET Time= DateAdd(d, ROUND(DateDiff(d, '2010-01-01', '2013-12-31') * RAND(CHECKSUM(NEWID())), 0),
      DATEADD(second,CHECKSUM(NEWID())%48000, '2010-01-01'))

This generates a random datetime between a given range.

Pieter_Daems
  • 1,234
  • 2
  • 14
  • 20
  • myeah. nice. love it. – Ash Nov 18 '15 at 13:53
  • Nice solution with the `RAND(CHECKSUM(NEWID()))` - I was doing a `RANK() OVER` ordering on a date, but due to data input errors (out of my control) there were two rows that had the exact same date and subsequently received the same rank, when the rows should have had a rank of 1 and 2 respectively. – puiu Jun 21 '16 at 19:28
  • 1
    This was great for random time as well. thanks. – nawfal Sep 15 '21 at 10:36
13

I adapted Jhonny's answer above to get dates from 10 years in the past:

SELECT dateadd(day, (abs(CHECKSUM(newid())) % 3650) * -1, getdate())

Note that this is SQLServer only.

8

I used this to set a date of birth between 1940 and 1985 for all of my test data

SET [Birth Date] = DATEADD(day, (ABS(CHECKSUM(NEWID())) % 16250), '1940-1-1 00:00:00.001')
Paul Cunningham
  • 115
  • 2
  • 9
5

The following code will fill the StartDate column of the FiscalYear table with random dates between two given dates:

-- First, let's declare the date range.
DECLARE @date_from DATETIME;
DECLARE @date_to DATETIME;

-- Set the start and date dates. In this case, we are using
-- the month of october, 2006.
SET @date_from = '1985-10-14';
SET @date_to = '2009-04-27';

UPDATE FiscalYear SET StartDate =  
(
    -- Remember, we want to add a random number to the
    -- start date. In SQL we can add days (as integers)
    -- to a date to increase the actually date/time
    -- object value.
    @date_from +
    (
        -- This will force our random number to be >= 0.
        ABS
        (
            -- This will give us a HUGE random number that
            -- might be negative or positive.
            CAST(CAST(NewID() AS BINARY(8)) AS INT)
        )

        -- Our random number might be HUGE. We can't have
        -- exceed the date range that we are given.
        -- Therefore, we have to take the modulus of the
        -- date range difference. This will give us between
        -- zero and one less than the date range.
        %

        -- To get the number of days in the date range, we
        -- can simply substrate the start date from the
        -- end date. At this point though, we have to cast
        -- to INT as SQL will not make any automatic
        -- conversions for us.
        CAST((@date_to - @date_from) AS INT)
    )
)
M. Jahedbozorgan
  • 6,914
  • 2
  • 46
  • 51
2

I was looking for a question similar to this that also generated a random time and I found this script. Thought it might be useful here:

DECLARE @DateFrom DATETime = '2001-01-01'
DECLARE @DateTo DATeTime = '2013-11-30'
DECLARE @DaysRandom Int= 0
DECLARE @MillisRandom Int=0

--get random number of days

select @DaysRandom= DATEDIFF(day,@DateFrom,@DateTo)
SELECT @DaysRandom = ROUND(((@DaysRandom -1) * RAND()), 0)

--get random millis
SELECT @MillisRandom = ROUND(((99999999) * RAND()), 0)

SELECT @DateTo = DATEADD(day, @DaysRandom, @DateFrom)
SELECT @DateTo = DATEADD(MILLISECOND, @MillisRandom, @DateTo)
SELECT @DateTo

I got it from here: http://crodrigues.com/sql-server-generate-random-datetime-within-a-range/

aug
  • 11,138
  • 9
  • 72
  • 93
1

Using the code below you can get a random integer between @Min (1) and @Max (365), then using the dateadd funection you can create random dates in the last year.

CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber
GO

CREATE FUNCTION RandNumber(@Min int, @Max int)
RETURNS int
AS
 BEGIN
 RETURN round(@Min + (select RandNumber from vRandNumber) * (@Max-@Min),0)
 END
GO

Update table1
set theDate = dateadd(d,0-dbo.RandNumber(1,365),getdate())
Jon Masters
  • 513
  • 3
  • 14
1

you can try getting a random number (positive or negative) then adding that number to a date (possibly system date).

For example (I don't have access to sqlserver right now so I could not verify syntax)

DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 1 - FLOOR(RAND(CAST(NEWID() AS binary(4))) * 365.25 * 90), 0)
northpole
  • 10,244
  • 7
  • 35
  • 58
  • In SQL Server 2019 (10 years later) this does work for multiple rows. `SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 1 - FLOOR(RAND(CAST(NEWID() AS BINARY(4))) * 365.25 * 90), 0), ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)` – Nielsvh Oct 23 '19 at 16:44
0

I combined several answers for myself, I think it it work for you. It took 40 seconds for me to execute this for 140k rows. i5, 1333MHZ, standart laptop hdd

 DECLARE @rank INT = 0;

WHILE @rank < yourmaxrow --(you can use Select count (*) from your table name as well)
BEGIN
   DECLARE @FromDate DATETIME = DATEADD(DAY, -720, GETDATE()) -- 2 years back
   DECLARE @ToDate   DATETIME = DATEADD(DAY, -1, GETDATE()) -- until yesterday

   DECLARE @Seconds INT = DATEDIFF(SECOND, @FromDate, @ToDate)
   DECLARE @Random INT = ROUND(((@Seconds-1) * RAND()), 0)
   DECLARE @Milliseconds INT = ROUND((999 * RAND()), 0)

update yourtablename
Set yourdatetiemcolumnname = DATEADD(MILLISECOND, @Milliseconds, DATEADD(SECOND, @Random, @FromDate))
WHERE Id = @rank
   SET @rank = @rank + 1;       
END;
Enes Okullu
  • 303
  • 3
  • 6