2012-03-10 37 views
16

Soy nuevo en el servidor sql. Necesito generar fechas aleatorias seleccionadas de un rango de fechas determinado. Al igual que la fecha de empleo de un empleado debe estar en cualquier lugar entre 2011-01-01 y 2011-12-31. Las fechas generadas deben insertarse aleatoriamente en una tabla de 1000 filas.¿Cómo insertar 1000 fechas aleatorias entre un rango determinado?

¿Puede alguien guiarme con mi consulta?

Respuesta

5

tengo a usted en este simple función que devuelve una fecha aleatoria entre rango de fechas:

create function date_rand (@fromDate date, @toDate date) returns date 
as 
begin 

declare @days_between int 
declare @days_rand int 

set @days_between = datediff(day,@fromDate,@toDate) 
set @days_rand = cast(RAND()*10000 as int) % @days_between 

return dateadd(day, @days_rand, @fromDate) 
end 

llamar a la función:

select dbo.date_rand('1/1/2001', '10/1/2001') 

puede combinar la función con un generador de fila:

;WITH Nbrs_3(n) AS (SELECT 1 UNION SELECT 0), 
Nbrs_2(n) AS (SELECT 1 FROM Nbrs_3 n1 CROSS JOIN Nbrs_3 n2), 
Nbrs_1(n) AS (SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2), 
Nbrs_0(n) AS (SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2), 
Nbrs (n) AS (SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2) 
SELECT dbo.date_rand('1/1/2001', '10/1/2001') 
FROM (SELECT ROW_NUMBER() OVER (ORDER BY n) 
FROM Nbrs) D (n) 
WHERE n <= 1000 

EDITADO

para generar números aleatorios usar:

RAND(CHECKSUM(NEWID())) 

en lugar de RAND()

editado II 'Uso no válido de un operador de efectuar lado '

función devuelve rand' dentro de una función 'error. Esto se debe a que no podemos usar funciones no deterministas como RAND() o NEWID().

Una solución consiste en create a view like:

create view myRandomNumber as 
select cast(RAND(CHECKSUM(NEWID()))*1000 as int) as new_rand 

y luego usarlo en función de:

... 
select @days_rand = new_rand % @days_between from myRandomNumber 
... 

o simplemente no utilizan la función y escribe en el expresion de selección. Escribí una función solo para explicar paso a paso la solución.

declare @fromdate date 
declare @todate date 
set @fromdate = '1/1/2001' 
set @todate = '10/1/2001' 
;WITH Nbrs_3(n) AS (SELECT 1 UNION SELECT 0), 
Nbrs_2(n) AS (SELECT 1 FROM Nbrs_3 n1 CROSS JOIN Nbrs_3 n2), 
Nbrs_1(n) AS (SELECT 1 FROM Nbrs_2 n1 CROSS JOIN Nbrs_2 n2), 
Nbrs_0(n) AS (SELECT 1 FROM Nbrs_1 n1 CROSS JOIN Nbrs_1 n2), 
Nbrs (n) AS (SELECT 1 FROM Nbrs_0 n1 CROSS JOIN Nbrs_0 n2) 
SELECT 
    dateadd(day, 
      cast(RAND(CHECKSUM(NEWID()))*1000 as int) % 
         datediff(day,@fromDate,@toDate), 
      @fromDate) 
FROM (SELECT ROW_NUMBER() OVER (ORDER BY n) 
FROM Nbrs) D (n) 
WHERE n <= 1000 

Puede test here this query.

+1

¿Qué versión de SQL Server utiliza? Probé en SQL Server 2012 y obtuve el 'Uso inválido de un operador de efecto secundario' rand 'dentro de una función. –

+0

Gracias @MikaelEriksson, he solucionado la consulta. Saludos. – danihp

35
declare @FromDate date = '2011-01-01' 
declare @ToDate date = '2011-12-31' 

select dateadd(day, 
       rand(checksum(newid()))*(1+datediff(day, @FromDate, @ToDate)), 
       @FromDate) 
0

Bueno, sé que esto es una cuestión de edad, sino que estaba vinculado a una más reciente así que ... Aquí están mis 2 centavos:

  1. tablas de bases de datos no están ordenados por naturaleza.
  2. Solo hay 365 fechas posibles en un año determinado, 366 si se trata de un año bisiesto.
  3. La duplicación de datos es un signo de diseño deficiente.

Basado en estas premisas, creo que realmente no hay una necesidad real de almacenar 1000 fechas aleatorias en una tabla, cuando es posible almacenar solo la fecha relevante y simplemente seleccionar cuántas filas y en cualquier orden necesitar.

Primero, almacene los datos dentro de la tabla. puede usar un Tally table para crear el intervalo de fechas relevante.
Una tabla Tally es una tabla que contiene una secuencia de números. por el bien de los argumentos, asumamos que ya ha creado su tabla de números de conteo entre 0 y 1,000,000.
You can check this link de la mejor manera de crear uno, personalmente me gusta este método:

-- create the tally table 
SELECT TOP 100000 IDENTITY (int ,0, 1) as num 
INTO Tally 
FROM sys.sysobjects 
CROSS JOIN sys.all_columns 

Ahora que tiene la tabla de conteo, es bastante simple de crear un calendario:

DECLARE @FromDate datetime = GETDATE(), 
     @ToDate datetime = DATEADD(YEAR, 1, GETDATE()) -- a year from now in my example 

;With CalendarCTE AS 
(
SELECT DATEADD(DAY, num, @FromDate) As caneldarDate 
FROM Tally 
WHERE num < DATEDIFF(DAY, @FromDate, @ToDate) 
) 

Ahora que ya tener el calendario y la tabla de recuento, es bastante simple usarlos para obtener cualquier cantidad de registros en el orden que desee. ¿Mil fechas ordenadas al azar? no hay problema:

SELECT TOP 1000 caneldarDate 
FROM CalendarCTE c 
CROSS JOIN Tally t 
WHERE t.num < 1000 
ORDER BY NEWID() 

guión completo, incluyendo crear y eliminar la tabla de conteo tomaron menos de un segundo para ejecutar:

-- create the tally table 
SELECT TOP 100000 IDENTITY (int ,0, 1) as num 
INTO Tally 
FROM sys.sysobjects 
CROSS JOIN sys.all_columns 

-- crealte the calendar cte: 
DECLARE @FromDate datetime = GETDATE(), 
     @ToDate datetime = DATEADD(YEAR, 1, GETDATE()) 

;With CalendarCTE AS 
(
SELECT DATEADD(DAY, num, @FromDate) As caneldarDate 
FROM Tally 
WHERE num < DATEDIFF(DAY, @FromDate, @ToDate) 
) 

-- select a 1000 random dates 
SELECT TOP 1000 caneldarDate 
FROM CalendarCTE c 
CROSS JOIN Tally t 
WHERE t.num < 1000 
ORDER BY NEWID() 

-- cleanup 
DROP TABLE Tally 
+0

Amigo, hay 365 días en un año, no 356: D – Yura

+0

@Yura corret. ligeramente disléxico ... –

+0

Meh! Definitivamente hay 8 días en mi semana, o al menos mi jefe me haría creer ... – Paul

Cuestiones relacionadas