2013-07-02 52 views
5

我正在使用微软的SQL Server 2008.我需要通过外键来聚合以随机获得单个值,但我很难过。考虑下面的表:随机聚集?

id   fk   val 
----------- ----------- ---- 
1   100   abc 
2   101   def 
3   102   ghi 
4   102   jkl 

期望的结果将是:

fk   val 
----------- ---- 
100   abc 
101   def 
102   ghi 

凡FK 102 VAL将随机或者是 “GHI” 或 “JKL”。

我尝试使用NEWID()来获取唯一的随机值,但是,由于NEWID()值根据子查询而不同,因此JOIN失败。

WITH withTable AS (
    SELECT id, fk, val, CAST(NEWID() AS CHAR(36)) random 
    FROM exampleTable 
) 
SELECT t1.fk, t1.val 
FROM withTable t1 
JOIN (
    SELECT fk, MAX(random) random 
    FROM withTable 
    GROUP BY fk 
) t2 ON t2.random = t1.random 
; 

我很难过。任何想法将不胜感激。

+1

@ypercube:在帖子的第一句话中提到... –

回答

6

我可能会用一种特殊的排名函数ROW_NUMBER()来思考它。

您基本上对每行应用一个数字,按fk分组,从1开始,随机使用NEWID()函数作为排序值进行排序。从此,您可以选择的所有行的行号为1。这种技术的效果是,它会随机哪一行被分配值1

WITH withTable(id, fk, val, rownum) AS 
(
    SELECT 
     id, fk, val, ROW_NUMBER() OVER (PARTITION BY fk ORDER BY NEWID()) 
    FROM 
     exampleTable 
) 
SELECT 
    * 
FROM 
    withTable 
WHERE 
    rownum = 1 

这种方法具有了额外的好处,它需要照顾分组和随机一次。

+0

你比我快:)但我创建了一个[SQL FIDDLE示例](http://sqlfiddle.com/#!6/dc46b/7) –

+0

谢谢,不知道PARTITION BY命令 – user1886415

+3

这样小心使用'NEWID',它是一个副作用的非确定性标量函数,通常会有违反直觉的行为。有[很少的保证](http://connect.microsoft.com/SQLServer/feedback/details/350485/bug-with-newid-and-table-expressions)(未来)标量函数有多少次执行 - 或者根本没有。这里的代码依赖于可能或不可能保留的特定行为。将ORDER BY NEWID()更改为ORDER BY(SELECT NEWID())'来查看示例。 –

1

你可以做到这一点不是聚集而是row_number()

select id, fk, val 
from (select t1.*, 
      row_number() over (partition by fk order by newid()) as seqnum 
     from withTable t1 
    ) t1 
where seqnum = 1 
0

一种选择是让属于同一FK到一个临时表中的值,然后通过NEWID()

SELECT TOP 1 ORDER

这应该适合你。