2012-11-18 18 views
8

Giả sử tôi có một bảng đơn giản với 3 trường: 'place', 'user' và 'bytes'. Giả sử, dưới một số bộ lọc, tôi muốn nhóm theo 'địa điểm' và cho mỗi 'địa điểm', để tổng hợp tất cả các byte cho địa điểm đó và chọn ngẫu nhiên người dùng cho địa điểm đó (thống nhất từ ​​tất cả người dùng phù hợp với 'nơi' bộ lọc và 'địa điểm' có liên quan). Nếu có chức năng tổng hợp "chọn ngẫu nhiên từ", tôi sẽ làm:SQL tổng hợp ngẫu nhiên

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

... nhưng tôi không thể tìm thấy chức năng tổng hợp như vậy. Tui bỏ lỡ điều gì vậy? Điều gì có thể là một cách tốt để đạt được điều này?

+4

RDBMS là gì? –

+0

Tôi không biết về bất kỳ RDBMS cá nhân nào có chức năng như vậy. Hầu hết cần phải sử dụng một số cơ chế khác để đạt được kết quả tương tự * (Chẳng hạn như gán một số ngẫu nhiên cho mỗi người dùng, sau đó chọn người dùng có giá trị cao nhất.) * Nhưng mỗi người sẽ có các khả năng khác nhau và mỗi người sẽ thực hiện khác nhau. Vì vậy, đây thực sự là một câu hỏi cụ thể của RDBMS. – MatBailie

+0

Nếu bạn đang sử dụng MySQL, chỉ cần viết sai 'GROUP BY' (ví dụ: không áp dụng tổng hợp trên người dùng) và nó sẽ chọn một hàng ngẫu nhiên. –

Trả lời

5

Nếu RDBMS của bạn hỗ trợ chức năng phân tích.

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; 

Đối với SQL Server Crypt_gen_random(4) hoặc NEWID() sẽ là ví dụ về một cái gì đó mà có thể được thay thế trong cho random_function()

2

Tôi nghĩ rằng câu hỏi của bạn là DBMS cụ thể. Nếu DBMS của bạn là MySql, bạn có thể sử dụng một giải pháp như thế này:

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; 

Các đơn hàng truy vấn ghi lại theo thứ tự ngẫu nhiên. Nhóm truy vấn bên ngoài theo số place, số tiền bytes và trả về người dùng ngẫu nhiên đầu tiên, vì người dùng không có chức năng tổng hợp và không thuộc nhóm theo mệnh đề.

0

tôi sẽ làm một chút của một biến thể của Martin của giải pháp:

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 

(Trong trường hợp newid() chỉ là một cách để có được một số ngẫu nhiên, tùy thuộc vào cơ sở dữ liệu.)

Đối với một số lý do, tôi thích cách tiếp cận này, bởi vì nó vẫn có hàm tổng hợp trong truy vấn bên ngoài. Nếu bạn đang tóm tắt một loạt các lĩnh vực, sau đó điều này có vẻ sạch hơn với tôi.

0

Với chức năng tùy chỉnh tổng hợp, bạn có thể viết các biểu thức đơn giản như:

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

SELECT_AT_RAMDOM sẽ là chức năng tùy chỉnh tổng hợp.

Đây chính xác là an implementation trong PostgreSQL.