2013-07-15 36 views
3

我正在尋找一種特殊的要求,從我對MySQL數據庫的查詢中尋找訂單以不同的方式。例如。在具有字段user_iduser_ratinguser_department的數據庫中具有以下數據。通過在MySQL查詢中隨機混合的記錄進行排序

+------------------------------------------------------+ 
|  user_id | user_rating | user_department | 
+------------------------------------------------------+ 
|   1  |  102  |   A   | 
|   2  |  33  |   B   | 
|   3  |  43  |   C   | 
|   4  |  54  |   A   | 
|   5  |  63  |   A   | 
|   6  |  214  |   B   | 
|   7  |  82  |   A   | 
|   8  |  87  |   C   | 
|   9  |  43  |   A   | 
|   10  |  98  |   A   | 
|   11  |  73  |   C   | 
|   12  |  31  |   A   | 
+------------------------------------------------------+ 

鑑於上述結構我想在他們的順序結果user_ratingeach_department排序,我需要在最高每個user_department 5個記錄其中INTIAL 3條應該是在他們的等級秩序,但休息2應該是隨機的。

因此在上述情況下,輸出將類似於:

+------------------------------------------------------+ 
|  user_id | user_rating | user_department | 
+------------------------------------------------------+ 
|   1  |  102  |   A   | 
|   10  |  98  |   A   | 
|   7  |  82  |   A   | 
|   12  |  31  |   A   | 
|   5  |  63  |   A   | 
|   6  |  214  |   B   | 
|   2  |  33  |   B   | 
|   8  |  87  |   C   | 
|   11  |  73  |   C   | 
|   3  |  43  |   C   | 
+------------------------------------------------------+ 

我嘗試過使用Web選項自定義順序由喜歡用場函數,但無法找到那麼多有用的在這裏。也嘗試使用子查詢來解決它,但該選項也看起來不可行,因爲MySql不允許我在查詢中一起使用IN和LIMIT關鍵字。

有沒有更好/更簡單的方法來解決這個問題。

+0

在您的上下文中,運行一系列SQL是否可行?例如。爲每個部門創建一個具有前三名的臨時表,然後運行另一個來自每個部門的2個隨機數,但臨時表中尚不存在? –

+0

是的,可以完成,第二個查詢隨機記錄應該在第一個查詢後留下的剩餘記錄中選擇。 – lalit

回答

1

這不完全是你正在尋找,但它提供了一種方法。

想法是使用group_concat()將每個部門的前5個值放在一個列中。此列的格式爲:

user_id:rating 

重複最多五次,用逗號分隔。如:

1:182,10:98,7:82,12:31,5:63 

,這是否是查詢:

select user_department, 
     substring_index(group_concat(concat(user_id, ':', user_rating) 
            order by user_rating desc 
            ), ',', 5) 
from t 
group by user_department; 

這不處理最後兩個值的隨機化。它將所有內容放在一行中。但是,我認爲這可能會有所幫助。

我的下一次嘗試技術上做你所要求的,但它運行的風險最後兩個「隨機」用戶可能是相同的。

它使用與上面相同的group_concat()技巧。但是,通過從列表中選擇不同的值,使用substring_index()

select u.user_id, user_id.user_rating, u.user_department 
from (select (case when n.n in (1, 2, 3) or ud.numusers <= 5 
        then cast(substring_index(substring_index(users, ',', n.n), ',', -1) as unsigned) 
        else CAST(substring_index(substring_index(users, ',', 4 + rand()*(num_users - 3)), ',', -1) as unsigned) 
       end) as user_id 
     from (select user_department, 
        group_concat(user_id order by user_rating desc) as users, 
        count(*) as numusers 
      from t 
      group by user_department 
      ) ud join 
      (select 1 as n union all select 2 union all select 3 union all select 4 union all select 5 
      ) n 
      on n.n <= ud.numusers 
    ) u join 
    t 
    on u.user_id = t.user_id 
order by user_department, user_rating desc 
+0

感謝您的回覆。是的,它看起來很有用。對我來說,主要問題是將第二個要求合併到第一個查詢中,因爲它應該應用於其餘記錄。 – lalit