2012-11-18 54 views
8

說我有一個簡單的表,有3個字段:'地點','用戶'和'字節'。比方說,在某個過濾器下,我想按'地點'分組,併爲每個「地點」合計該地點的所有字節,並隨機選擇該地點的用戶(統一來自所有符合'where'過濾器和相關'地點')。如果有一個「隨機選擇」聚合函數,我會這樣做:SQL隨機聚合

SELECT place, SUM(bytes), SELECT_AT_RANDOM(user) WHERE .... GROUP BY place; 

...但我找不到這樣一個聚合函數。我錯過了什麼嗎?什麼可能是一個很好的方法來實現這一目標?

+4

這是什麼RDBMS? –

+0

我不知道任何具有這種功能的個人RDBMS。大多數需要使用一些其他機制來實現相同的結果*(例如爲每個用戶分配一個隨機數,然後選擇具有最高值的用戶)。*但每個都有不同的功能,並且每個功能的表現都不相同。所以,這確實是一個RDBMS特定的問題。 – MatBailie

+0

如果您使用的是MySQL,只需編寫一個不正確的「GROUP BY」(例如,不要在用戶上應用聚合),它將隨機選擇一行。 –

回答

5

如果您的RDBMS支持分析功能。

WITH T 
    AS (SELECT place, 
       Sum(bytes) OVER (PARTITION BY place) AS Sum_bytes, 
       user, 
       Row_number() OVER (PARTITION BY place ORDER BY random_function()) AS RN 
     FROM YourTable 
     WHERE ....) 
SELECT place, 
     Sum_bytes, 
     user 
FROM T 
WHERE RN = 1; 

對於SQL Server Crypt_gen_random(4)NEWID()會的東西,可以爲random_function()

2

被取代的例子,我認爲你的問題是DBMS特定的。如果您的DBMS是MySql,您可以使用類似這樣的解決方案:

SELECT place_rand.place, SUM(place_rand.bytes), place_rand.user as random_user 
FROM 
    (SELECT place, bytes, user 
    FROM place 
    WHERE ... 
    ORDER BY rand()) place_rand 
GROUP BY 
    place_rand.place; 

子查詢訂單以隨機順序記錄。外部查詢按place進行分組,總計bytes,並返回第一個隨機用戶,因爲用戶不在聚合函數中,也不在group by子句中。

0

我會做有點變化對馬丁的解決方案:

select place, sum(bytes), max(case when seqnum = 1 then user end) as random_user 
from (select place, bytes, 
      row_number() over (partition by place order by newid()) as sequm 
     from t 
    ) t 
group by place 

(其中NEWID()僅僅是一個得到一個隨機數,取決於數據庫的方式。)

對於一些原因,我更喜歡這種方法,因爲它在外部查詢中仍然具有聚合功能。如果你總結了一堆領域,那麼這對我來說似乎更清潔。

0

使用自定義聚合函數,你可以寫表達式一樣簡單:

SELECT place, SUM(bytes), SELECT_AT_RANDOM(user) WHERE .... GROUP BY place; 

SELECT_AT_RAMDOM將是自定義的聚合函數。

這裏正好是an implementationPostgreSQL