문제

페이징과 같은 목적으로 반복 가능한 방식으로 결과를 무작위로 분류하고 싶습니다. 이 newID ()는 동일한 결과를 다시 구축 할 수 없다는 점에서 너무 무작위입니다. Rand (Seed)의 주문은 동일한 씨앗과 같은 임의의 수집이 발생하는 것과 같은 이상적입니다. 불행히도, rand () 상태는 모든 행에 재설정됩니다. 누구든지 해결책이 있습니까?

declare @seed as int;
set @seed = 1000;

create table temp (
id int,
date datetime)

insert into temp (id, date) values (1,'20090119')
insert into temp (id, date) values (2,'20090118')
insert into temp (id, date) values (3,'20090117')
insert into temp (id, date) values (4,'20090116')
insert into temp (id, date) values (5,'20090115')
insert into temp (id, date) values (6,'20090114')

-- re-seeds for every item
select *, RAND(), RAND(id+@seed) as r from temp order by r
--1 2009-01-19 00:00:00.000 0.277720118060575   0.732224964471124
--2 2009-01-18 00:00:00.000 0.277720118060575   0.732243597442382
--3 2009-01-17 00:00:00.000 0.277720118060575   0.73226223041364
--4 2009-01-16 00:00:00.000 0.277720118060575   0.732280863384898
--5 2009-01-15 00:00:00.000 0.277720118060575   0.732299496356156
--6 2009-01-14 00:00:00.000 0.277720118060575   0.732318129327415
-- Note how the last column is +=~0.00002

drop table temp

-- interestingly this works:
select RAND(@seed), RAND()
--0.732206331499865 0.306382810665955

나는 rand (id)를 시도했지만 정렬 된 것으로 판명되었습니다. 분명히 랜드 (n) <랜드 (n+1)

도움이 되었습니까?

해결책

Gkrogers Hash의 제안을 제안하는 것은 이것이 훌륭하게 작동합니다. 공연에 대한 생각이 있습니까?

declare @seed as int;
set @seed = 10;

create table temp (
id int,
date datetime)

insert into temp (id, date) values (1,'20090119')
insert into temp (id, date) values (2,'20090118')
insert into temp (id, date) values (3,'20090117')
insert into temp (id, date) values (4,'20090116')
insert into temp (id, date) values (5,'20090115')
insert into temp (id, date) values (6,'20090114')

-- re-seeds for every item
select *, HASHBYTES('md5',cast(id+@seed as varchar)) r
from temp order by r
--1 2009-01-19 00:00:00.000 0x6512BD43D9CAA6E02C990B0A82652DCA
--5 2009-01-15 00:00:00.000 0x9BF31C7FF062936A96D3C8BD1F8F2FF3
--4 2009-01-16 00:00:00.000 0xAAB3238922BCC25A6F606EB525FFDC56
--2 2009-01-18 00:00:00.000 0xC20AD4D76FE97759AA27A0C99BFF6710
--3 2009-01-17 00:00:00.000 0xC51CE410C124A10E0DB5E4B97FC2AF39
--6 2009-01-14 00:00:00.000 0xC74D97B01EAE257E44AA9D5BADE97BAF

drop table temp

편집 : 쿼리에서 사용되는 @seed의 선언은 동적 SQL을 사용하는 경우 매개 변수 또는 상수 int로 대체 할 수 있습니다. (TSQL 방식으로 @Int의 선언이 필요하지 않습니다)

다른 팁

각 행의 값을 사용하여 RAND 기능을 다시 평가할 수 있습니다.

Select *, Rand(@seed + id) as r from temp order by r

ID를 추가하면 랜드가 각 행에 대해 재조정되도록합니다. 그러나 씨앗 값의 경우 항상 동일한 순서의 행을 되 찾을 수 있습니다 (테이블이 변하지 않는 경우).

해시를 만드는 것은 시드 임의 숫자를 만드는 것보다 훨씬 더 많은 시간이 걸릴 수 있습니다.

랜드 ([SEED])의 우리의 입장에서 더 많은 변화를 얻으려면 [시드]를 크게 다양하게 만들어야합니다. 아마도 ...

SELECT
    *,
    RAND(id * 9999)    AS [r]
FROM
   temp
ORDER BY
   r

상수를 사용하면 요청한 복제 성을 보장합니다. 그러나 테이블이 충분히 커질 것으로 예상하면 (ID * 9999)의 결과에주의하십시오 ...

SELECT *, checksum(id) AS r FROM table ORDER BY r

이런 종류의 작품. checksum ()의 출력이 나에게 그다지 무작위로 보이지는 않지만. 그만큼 MSDN 문서 상태 :

...], 체크섬을 사용하여 응용 프로그램이 때때로 변경을 누락 할 수 없다면 값이 변경되었는지 여부를 감지하는 것이 좋습니다. 대신 해시 테스를 사용하는 것을 고려하십시오. MD5 해시 알고리즘이 지정되면, 해시 베이트가 두 개의 다른 입력에 대해 동일한 결과를 반환 할 확률은 체크섬의 것보다 훨씬 낮습니다.

그러나 더 빠를 수도 있습니다.

읽은 후에는이 방법이 허용되는 방법입니다.

Select Rand(@seed) -- now rand is seeded

Select *, 0 * id + Rand() as r from temp order by r

표현식에 ID가 있으면 모든 행이 재평가 될 수 있습니다. 그러나 그것을 0만큼 곱하면 RAND의 결과에 영향을 미치지 않도록합니다.

일을하는 것은 얼마나 끔찍한 방법입니다!

이것은 과거에 나에게 잘 작동했으며 모든 테이블에 적용될 수 있습니다 (절 순서에 의한 볼트에 의해 볼트로 볼트) :

SELECT *
FROM MY_TABLE
ORDER BY  
  (SELECT ABS(CAST(NEWID() AS BINARY(6)) % 1000) + 1);
create table temp (
id int,
date datetime)

insert into temp (id, date) values (1,'20090119')
insert into temp (id, date) values (2,'20090118')
insert into temp (id, date) values (3,'20090117')
insert into temp (id, date) values (4,'20090116')
insert into temp (id, date) values (5,'20090115')
insert into temp (id, date) values (6,'20090114')

-- re-seeds for every item
select *, NEWID() r
from temp order by r

drop table temp
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top