2013-07-02 50 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

這應該適合你。