2012-03-10 13 views
16

Jestem nowy na serwerze sql. Potrzebuję generować przypadkowe daty wybrane z danego zakresu dat. Podobnie jak data zatrudnienia pracownika powinna być w dowolnym miejscu między 2011-01-01 i 2011-12-31. Wygenerowane daty powinny być losowo wstawiane do tabeli 1000 wierszy.Jak wstawić 1000 losowych dat z podanego zakresu?

Czy ktoś może mi pomóc?

Odpowiedz

5

mam napisać do Ciebie tę prostą funkcję, która zwraca losową datę między Zakres dat:

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 

do wywołania funkcji:

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

można łączyć funkcji z generatorem rzędu:

;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 

EDYTOWANA

do generowania liczb losowych użyć:

RAND(CHECKSUM(NEWID())) 

zamiast RAND()

Edited II „nieprawidłowe użycie bocznej dokonania operatora

zwraca rand" w ramach funkcja "błąd. Dzieje się tak, ponieważ nie możemy używać niedeterministycznych funkcji, takich jak RAND() lub NEWID().

Rozwiązaniem jest create a view like:

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

a następnie używać go w funkcji:

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

prosty lub nie korzystać z funkcji i napisać wprowadzić wyrażenie na select. Napisałem funkcję tylko po to, aby wyjaśnić krok po kroku rozwiązanie.

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 

Możesz test here this query.

+1

Jaka wersja SQL Server używacie? Testowałem w SQL Server 2012 i otrzymałem komunikat "Niewłaściwe użycie operatora" rand "w funkcji". –

+0

Dzięki @MikaelEriksson, poprawiłem zapytanie. Pozdrowienia. – 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

Cóż, wiem, że jest to stara sprawa, ale to było związane z nowszej więc ... Oto moje 2 centy:

  1. tabele bazy danych są nieposortowane przez naturę.
  2. Istnieje tylko 365 możliwych dat w danym roku, 366 jeśli jest to rok przestępny.
  3. Powielone dane są oznaką złego projektu.

Na podstawie tych przesłanek uważam, że tak naprawdę nie ma rzeczywistej potrzeby przechowywania 1000 losowych dat w tabeli, kiedy możliwe jest zapisanie tylko odpowiedniej daty i wystarczy wybrać liczbę wierszy w dowolnej kolejności potrzeba.

Najpierw zapisz dane w tabeli. możesz użyć Tally table, aby utworzyć odpowiedni zakres dat.
Tabela Tally jest tabelą zawierającą ciąg cyfr. ze względu na argument, załóżmy, że już stworzyłeś tabelę z liczbami od 0 do 1 000 000.
You can check this link dla najlepszej drodze do stworzenia jednego, osobiście lubię tę metodę:

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

Teraz masz tabelę Tally, jest to dość proste do stworzenia kalendarza:

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) 
) 

teraz, że Mają kalendarz i tabelę, jest dość proste, aby użyć ich do uzyskania dowolnej liczby rekordów w dowolnej kolejności. Tysiąc losowo zamówionych dat? nie ma problemu:

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

Pełny skrypt, w tym tworzenie i upuszczenie tabeli sygnalizacyjną trwało krócej niż sekundę, aby wykonać:

-- 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

Koleś, istnieją 365 dni w roku, nie 356: D – Yura

+0

@ Corure yury. lekko dyslektyczny ... –

+0

Meh! W moim tygodniu jest zdecydowanie 8 dni, a więc mój szef kazałby mi uwierzyć ... – Paul

Powiązane problemy