2015-07-18 54 views
5

在我的MySQL數據庫中,我有一個包含不同類別不同問題的表。如何從MySQL中的每個類別獲取RANDOM記錄?

我想編寫返回3個RANDOM問題的每個類別的sql語句。

下面是示例的數據庫記錄:

id question category 
1 Question A 1 
2 Question B 1 
3 Question C 1 
4 Question D 1 
5 Question D 1 
6 Question F 2 
7 Question G 2 
8 Question H 2 
9 Question I 2 
10 Question J 2 
11 Question K 3 
12 Question L 3 
13 Question M 3 
14 Question N 3 
15 Question O 3 
16 Question P 3 

這裏是輸出/選擇並從上述列表中的每個類別的所有問題混洗3隨機的結果:

2 Question B 1 
4 Question D 1 
3 Question C 1 
10 Question J 2 
7 Question G 2 
9 Question I 2 
11 Question K 3 
15 Question P 3 
13 Question M 3 

我到目前爲止玩過以下測試語句:

SELECT * FROM `random` ORDER BY RAND() LIMIT 0,3; 

這隻返回所有類別中的3個RANDOM問題。

而且我後來看了例如在此鏈接: MYSQL select random of each of the categories

並試用了此:

(SELECT * FROM `random` WHERE category = 1 ORDER BY RAND() LIMIT 3) 
UNION ALL 
(SELECT * FROM `random` WHERE category = 2 ORDER BY RAND() LIMIT 3) 
UNION ALL 
(SELECT * FROM `random` WHERE category = 3 ORDER BY RAND() LIMIT 3) 

但在這裏我需要手動每個類別添加。

我的問題:我想知道是否完全可以從每個類別的所有類別(自動)中獲取3 RANDOM記錄/行?


編輯

這不是問題,而是幫助的一部分。

虛擬數據創建 查詢代碼表叫random和創建的存儲過程稱爲create_random當您運行存儲的過程,它會創建隨機表內隨機虛擬數據:

DELIMITER $$ 
DROP TABLE IF EXISTS `random`; 
DROP PROCEDURE IF EXISTS `create_random` $$ 

CREATE TABLE `random` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `question` VARCHAR(50) NULL DEFAULT NULL, 
    `category` VARCHAR(50) NULL DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) 
COLLATE='latin1_swedish_ci' 
ENGINE=InnoDB 
AUTO_INCREMENT=401 
; 

CREATE DEFINER=`root`@`localhost` 
PROCEDURE `create_random`() 
    LANGUAGE SQL 
    NOT DETERMINISTIC 
    CONTAINS SQL 
    SQL SECURITY DEFINER 
    COMMENT '' 

BEGIN 

DECLARE v_max int unsigned DEFAULT 100; 
DECLARE v_counter int unsigned DEFAULT 0; 
DECLARE cat_counter int unsigned DEFAULT 0; 

    TRUNCATE TABLE `random`; 
    START TRANSACTION; 
    WHILE v_counter < v_max DO 
    IF v_counter %10=0 THEN SET cat_counter=cat_counter+1; 
    END IF; 
    INSERT INTO `random` (question, category) VALUES (CONCAT('Question', FLOOR(0 + (RAND() * 65535))), cat_counter); 
    SET v_counter=v_counter+1; 
    END WHILE; 
    COMMIT; 
END 

注:我試過所有的答案,一切正常。 Gordon Linoff和pjanaway回答只從前3個或最後3個問題中選擇RANDOM,我已經檢查過Gordon的答案,因爲他首先回答,但這並不意味着其他答案不好,他們都很好,並且要由用戶選擇正確的答案或答案的組合。我喜歡所有的答案並將它們投票。德魯·皮爾斯對這個問題重新回答,現在更加有趣,幾乎接近目標。謝謝大家。

+0

如果問題中的單詞也是隨機的,那真的很酷。但嚴重的是,你看起來有90%。您是否希望將演示文稿順序打亂一點(即,不是其中一個類別)?或者它是我最後三次閱讀的最後一部分:你是否希望自動爲每個新類別自動添加新聯合?可能是後者,對不起。 – Drew

+0

@DrewPierce,是的,思想sql語句應該改變同一類別的問題,所以人們回答或得到問題不應該期望一直得到相同的問題。這個例子很小,但是每個類別都會有很多問題,想象一下,如果我每週添加新的類別,那麼我需要不斷修改我的sql語句,但是如果我自動以某種方式執行,那麼它會讓我的一天更容易;)大聲笑 –

+0

這個問題希望能夠爲你帶來一些值得讚賞的觀點,因爲它似乎在許多場合非常有用! – Drew

回答

3

是的,你可以通過枚舉行,然後取前三名做到這一點:

select r.id, r.question, r.category 
from (select r.*, 
      (@rn := if(@c = category, @rn + 1, 
         if(@c := category, 1, 1) 
         ) 
      ) as seqnum 
     from `random` r cross join 
      (select @rn := 0, @c := -1) params 
     order by category, rand() 
    ) r 
where seqnum <= 3; 
+0

問候戈登。我對結果有問題。可能最好在pj的答案下閱讀下面的**首先**,然後這個與你的內部查詢。 http://pastie.org/10300277 – Drew

+0

這裏有一個小小的挑戰。現在我已經構建了一個更大的隨機數據庫進行測試,當我運行你的代碼和pjanaway時,他們都選擇了三個問題並繼續洗牌,但是當我再次運行代碼時,它保留了相同的問題,這個想法是我有三個以上的問題在每個類別中的問題,它應該採取其中3個,並從所有問題中隨機挑選並洗牌。在你的代碼中,它只保留前三個問題和@pjanaway它最後三個問題? –

+1

@maytham。 。 。如果代碼返回相同的三個問題,則有一種可能性是將隨機數生成器的種子重置。您可以嘗試手動設置它以查看是否得到不同的結果(https://dev.mysql.com/doc/refman/5.6/en/mathematical-functions.html#function_rand)。 –

4

除了對方的回答,這也是另一種方式來做到這一點。

SELECT r.* FROM random r 
WHERE (
    SELECT COUNT(*) FROM random r1 
    WHERE r.category = r1.category AND r.id < r1.id 
) <= 2 
ORDER BY r.category ASC, RAND() 
+0

我不能讓Gordon去工作,但我可以讓這個工作。將顯示一個pastie – Drew

+0

@DrewPierce這個代碼工作更緊湊,我們已經更新了Gordon的答案你有沒有嘗試過最新的更新? –

+0

是的,我嘗試了3次,我知道它已經更新,但我會再試一次 – Drew

1
create schema so_gibberish; -- creates database 
use so_gibberish; -- use it 

-- drop table random; -- during debug 
create table random 
( id int auto_increment primary key, 
    question varchar(50) not null, 
    category int not null, 
    randomOrder int not null, 
    key (category) 
); 

-- drop table questions_for_user; -- during debug 
create table questions_for_user 
( physcOrder int auto_increment primary key, 
    id int not null, 
    question varchar(50) not null, 
    category int not null, 
    randomOrder int not null, 
    key (category) 
); 

創建一個存儲過程來插入隨機的問題。當你打電話時,它會創建300個。

DELIMITER $$ 
drop procedure if exists createRandomQuestions$$ 
-- 17 categories of questions randomly created. yes random word questions and categories. 

create procedure createRandomQuestions() 
BEGIN 
set @i=1; 
WHILE @i<=300 DO 
insert random (question,category) values ('xxx',1); 
SELECT @lid:=LAST_INSERT_ID(); -- use id to seed, next 8 guaranteed different i think 

UPDATE random SET question=concat(
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed:=round(rand(@lid)*4294967296))*36+1, 1), 
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1), 
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1), 
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1), 
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1), 
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1), 
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1), 
substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', rand(@seed)*36+1, 1), ' ?' 
), category=floor(rand()*17+1),randomOrder=0 
WHERE [email protected]; 
set @[email protected]+1; 
END WHILE; 
END; 
$$ 
DELIMITER ; 

調用它:

call createRandomQuestions(); 

檢查:

select category,count(*) from random group by category order by category; 
select count(*) from random; 
select * from random limit 10; 

現在得到每個類別的三個隨機問題,應要求用戶。

想出一個很好的隨機SEEDING算法。以下是存根,最好使用外部資源(如HTTP)的服務等

update random set randomOrder=rand()*unix_timestamp(); 
truncate table questions_for_user; 
insert into questions_for_user (id,question,category,randomOrder) 
select id,question,category,randomOrder from random order by rand(); 

select r.* 
FROM questions_for_user r 
WHERE 
(SELECT COUNT(*) FROM random r1 WHERE r.category = r1.category AND r.id < r1.id) <= 2 
ORDER by r.category ASC, randomOrder; 

+------------+-----+------------+----------+-------------+ 
| physcOrder | id | question | category | randomOrder | 
+------------+-----+------------+----------+-------------+ 
|  297 | 266 | JNQH26DD ? |  1 | 841700408 | 
|  247 | 286 | ORK15577 ? |  1 | 980764662 | 
|   54 | 267 | T2HPRW88 ? |  1 | 1331420535 | 
|  190 | 275 | U5BFCUFF ? |  2 | 836160445 | 
|  192 | 285 | E3KDJ144 ? |  2 | 1166207975 | 
|   55 | 293 | GFWQ0BEE ? |  2 | 1356597807 | 
|  266 | 296 | 8MJCWR55 ? |  3 | 1121232849 | 
|  173 | 288 | 6GGOI2CC ? |  3 | 1209081435 | 
|  205 | 231 | LQMYMV44 ? |  3 | 1330946482 | 
|  103 | 289 | FUODJHJJ ? |  4 | 392498036 | 
|  274 | 295 | Y85VNBWW ? |  4 | 613800522 | 
|  204 | 280 | 441X1YTT ? |  4 | 1141251557 | 
|  162 | 273 | CC5FGKFF ? |  5 | 99041401 | 
|   36 | 252 | Y7V58ZEE ? |  5 | 1124240820 | 
|  143 | 234 | DWZULKBB ? |  5 | 1286225785 | 
|   15 | 276 | 3J1KGJZZ ? |  6 | 51285374 | 
|  265 | 294 | PTEMZ7GG ? |  6 | 649256602 | 
|   91 | 271 | TNG23R11 ? |  6 | 1393790410 | 
|   90 | 277 | DXE1W0GG ? |  7 | 622567356 | 
|   20 | 274 | LQTFS7RR ? |  7 | 1376505632 | 
|  121 | 279 | VQN6TVSS ? |  7 | 1428714367 | 
|  268 | 265 | A99UU1YY ? |  8 | 479923553 | 
|  242 | 284 | 5PDRR5YY ? |  8 | 658551160 | 
|  283 | 282 | NWZSPCZZ ? |  8 | 802197234 | 
|  114 | 233 | 3IHU1YKK ? |  9 | 118146688 | 
|   85 | 226 | BQTD6A44 ? |  9 | 292147382 | 
|  255 | 291 | YNT0YN11 ? |  9 | 559911752 | 
|  281 | 258 | IHK46577 ? |  10 | 196799301 | 
|  198 | 263 | SHEVXPBB ? |  10 | 545833955 | 
|   11 | 298 | QEHHSAEE ? |  10 | 1087006220 | 
|   60 | 250 | GEH9PVBB ? |  11 | 225193615 | 
|  270 | 272 | 3YY2EMM ? |  11 | 1143544695 | 
|  300 | 290 | O8B4WRCC ? |  11 | 1209867696 | 
|   68 | 246 | FTEEVJ00 ? |  12 | 608441021 | 
|  177 | 244 | X1JYHUBB ? |  12 | 1192309224 | 
|  208 | 240 | W771N588 ? |  12 | 1347800170 | 
|  249 | 300 | 97V6UXYY ? |  13 | 500846709 | 
|  100 | 292 | 71JZTMQQ ? |  13 | 607266604 | 
|   38 | 283 | WBQ0DGLL ? |  13 | 1187952919 | 
|   87 | 235 | MBPPXJ44 ? |  14 | 327445349 | 
|  178 | 242 | EZ1ET3ZZ ? |  14 | 852480639 | 
|   62 | 281 | EIHVH3ZZ ? |  14 | 1420114728 | 
|   95 | 251 | PT8E2CII ? |  15 | 72502146 | 
|  170 | 253 | 8L35PFYY ? |  15 | 1091765038 | 
|   65 | 287 | X5ZR3LHH ? |  15 | 1405199431 | 
|  138 | 278 | MBW03OUU ? |  16 | 84358922 | 
|   7 | 268 | 2G4G42WW ? |  16 | 1257379717 | 
|   1 | 299 | ZT8QRRMM ? |  16 | 1327297420 | 
|  221 | 297 | H00HLNRR ? |  17 | 890140945 | 
|   40 | 204 | O7VUW2NN ? |  17 | 1238474743 | 
|  122 | 229 | 3XEZG0PP ? |  17 | 1359337651 | 
+------------+-----+------------+----------+-------------+ 
51 rows in set (0.01 sec) 

再次運行它下一個用戶或同一個人:

update random set randomOrder=rand()*unix_timestamp(); 
truncate table questions_for_user; 
insert into questions_for_user (id,question,category,randomOrder) 
select id,question,category,randomOrder from random order by rand(); 

select r.* 
FROM questions_for_user r 
WHERE 
(SELECT COUNT(*) FROM random r1 WHERE r.category = r1.category AND r.id < r1.id) <= 2 
ORDER by r.category ASC, randomOrder; 

+------------+-----+------------+----------+-------------+ 
| physcOrder | id | question | category | randomOrder | 
+------------+-----+------------+----------+-------------+ 
|  112 | 286 | ORK15577 ? |  1 | 193281314 | 
|  176 | 266 | JNQH26DD ? |  1 | 530153269 | 
|  296 | 267 | T2HPRW88 ? |  1 | 891041924 | 
|   37 | 293 | GFWQ0BEE ? |  2 | 222852606 | 
|  239 | 285 | E3KDJ144 ? |  2 | 679635152 | 
|  262 | 275 | U5BFCUFF ? |  2 | 846163956 | 
|   95 | 288 | 6GGOI2CC ? |  3 | 1244253481 | 
|   81 | 231 | LQMYMV44 ? |  3 | 1380298624 | 
|   59 | 296 | 8MJCWR55 ? |  3 | 1420850554 | 
|   28 | 295 | Y85VNBWW ? |  4 | 806083444 | 
|   30 | 289 | FUODJHJJ ? |  4 | 814854070 | 
|   34 | 280 | 441X1YTT ? |  4 | 1119188021 | 
|  232 | 234 | DWZULKBB ? |  5 | 296692881 | 
|  295 | 273 | CC5FGKFF ? |  5 | 337915901 | 
|  140 | 252 | Y7V58ZEE ? |  5 | 644987638 | 
|  257 | 271 | TNG23R11 ? |  6 | 619359840 | 
|   27 | 294 | PTEMZ7GG ? |  6 | 869855570 | 
|  218 | 276 | 3J1KGJZZ ? |  6 | 1390090875 | 
|   64 | 279 | VQN6TVSS ? |  7 | 33942495 | 
|  290 | 277 | DXE1W0GG ? |  7 | 100007602 | 
|  173 | 274 | LQTFS7RR ? |  7 | 946909650 | 
|  291 | 265 | A99UU1YY ? |  8 | 107468716 | 
|   49 | 284 | 5PDRR5YY ? |  8 | 1068298164 | 
|  228 | 282 | NWZSPCZZ ? |  8 | 1115906220 | 
|  284 | 226 | BQTD6A44 ? |  9 | 45678738 | 
|  179 | 291 | YNT0YN11 ? |  9 | 700305900 | 
|  164 | 233 | 3IHU1YKK ? |  9 | 1416089612 | 
|  193 | 258 | IHK46577 ? |  10 | 460111512 | 
|  214 | 298 | QEHHSAEE ? |  10 | 482322673 | 
|   7 | 263 | SHEVXPBB ? |  10 | 766681927 | 
|  178 | 290 | O8B4WRCC ? |  11 | 341509950 | 
|   31 | 272 | 3YY2EMM ? |  11 | 726662739 | 
|  297 | 250 | GEH9PVBB ? |  11 | 1386568968 | 
|   32 | 240 | W771N588 ? |  12 | 303493686 | 
|  283 | 246 | FTEEVJ00 ? |  12 | 710591266 | 
|  177 | 244 | X1JYHUBB ? |  12 | 916685336 | 
|  212 | 283 | WBQ0DGLL ? |  13 | 595739692 | 
|  159 | 300 | 97V6UXYY ? |  13 | 688431139 | 
|   52 | 292 | 71JZTMQQ ? |  13 | 1039681379 | 
|   56 | 235 | MBPPXJ44 ? |  14 | 109832248 | 
|  207 | 242 | EZ1ET3ZZ ? |  14 | 418951740 | 
|   6 | 281 | EIHVH3ZZ ? |  14 | 1182157711 | 
|  149 | 287 | X5ZR3LHH ? |  15 | 364819476 | 
|   88 | 251 | PT8E2CII ? |  15 | 673475236 | 
|  123 | 253 | 8L35PFYY ? |  15 | 1204512525 | 
|  190 | 278 | MBW03OUU ? |  16 | 641720378 | 
|  160 | 299 | ZT8QRRMM ? |  16 | 1289470813 | 
|   75 | 268 | 2G4G42WW ? |  16 | 1427431541 | 
|  202 | 297 | H00HLNRR ? |  17 | 374047531 | 
|  243 | 204 | O7VUW2NN ? |  17 | 951026810 | 
|  300 | 229 | 3XEZG0PP ? |  17 | 1319302198 | 
+------------+-----+------------+----------+-------------+ 
51 rows in set (0.01 sec) 

所以問題是不同

要獲得一個洗牌意義上的最後結果:

select r.* 
FROM questions_for_user r 
WHERE 
(SELECT COUNT(*) FROM random r1 WHERE r.category = r1.category AND r.id < r1.id) <= 2 
ORDER by randomOrder; 

+------------+-----+------------+----------+-------------+ 
| physcOrder | id | question | category | randomOrder | 
+------------+-----+------------+----------+-------------+ 
|   64 | 279 | VQN6TVSS ? |  7 | 33942495 | 
|  284 | 226 | BQTD6A44 ? |  9 | 45678738 | 
|  290 | 277 | DXE1W0GG ? |  7 | 100007602 | 
|  291 | 265 | A99UU1YY ? |  8 | 107468716 | 
|   56 | 235 | MBPPXJ44 ? |  14 | 109832248 | 
|  112 | 286 | ORK15577 ? |  1 | 193281314 | 
|   37 | 293 | GFWQ0BEE ? |  2 | 222852606 | 
|  232 | 234 | DWZULKBB ? |  5 | 296692881 | 
|   32 | 240 | W771N588 ? |  12 | 303493686 | 
|  295 | 273 | CC5FGKFF ? |  5 | 337915901 | 
|  178 | 290 | O8B4WRCC ? |  11 | 341509950 | 
|  149 | 287 | X5ZR3LHH ? |  15 | 364819476 | 
|  202 | 297 | H00HLNRR ? |  17 | 374047531 | 
|  207 | 242 | EZ1ET3ZZ ? |  14 | 418951740 | 
|  193 | 258 | IHK46577 ? |  10 | 460111512 | 
|  214 | 298 | QEHHSAEE ? |  10 | 482322673 | 
|  176 | 266 | JNQH26DD ? |  1 | 530153269 | 
|  212 | 283 | WBQ0DGLL ? |  13 | 595739692 | 
|  257 | 271 | TNG23R11 ? |  6 | 619359840 | 
|  190 | 278 | MBW03OUU ? |  16 | 641720378 | 
|  140 | 252 | Y7V58ZEE ? |  5 | 644987638 | 
|   88 | 251 | PT8E2CII ? |  15 | 673475236 | 
|  239 | 285 | E3KDJ144 ? |  2 | 679635152 | 
|  159 | 300 | 97V6UXYY ? |  13 | 688431139 | 
|  179 | 291 | YNT0YN11 ? |  9 | 700305900 | 
|  283 | 246 | FTEEVJ00 ? |  12 | 710591266 | 
|   31 | 272 | 3YY2EMM ? |  11 | 726662739 | 
|   7 | 263 | SHEVXPBB ? |  10 | 766681927 | 
|   28 | 295 | Y85VNBWW ? |  4 | 806083444 | 
|   30 | 289 | FUODJHJJ ? |  4 | 814854070 | 
|  262 | 275 | U5BFCUFF ? |  2 | 846163956 | 
|   27 | 294 | PTEMZ7GG ? |  6 | 869855570 | 
|  296 | 267 | T2HPRW88 ? |  1 | 891041924 | 
|  177 | 244 | X1JYHUBB ? |  12 | 916685336 | 
|  173 | 274 | LQTFS7RR ? |  7 | 946909650 | 
|  243 | 204 | O7VUW2NN ? |  17 | 951026810 | 
|   52 | 292 | 71JZTMQQ ? |  13 | 1039681379 | 
|   49 | 284 | 5PDRR5YY ? |  8 | 1068298164 | 
|  228 | 282 | NWZSPCZZ ? |  8 | 1115906220 | 
|   34 | 280 | 441X1YTT ? |  4 | 1119188021 | 
|   6 | 281 | EIHVH3ZZ ? |  14 | 1182157711 | 
|  123 | 253 | 8L35PFYY ? |  15 | 1204512525 | 
|   95 | 288 | 6GGOI2CC ? |  3 | 1244253481 | 
|  160 | 299 | ZT8QRRMM ? |  16 | 1289470813 | 
|  300 | 229 | 3XEZG0PP ? |  17 | 1319302198 | 
|   81 | 231 | LQMYMV44 ? |  3 | 1380298624 | 
|  297 | 250 | GEH9PVBB ? |  11 | 1386568968 | 
|  218 | 276 | 3J1KGJZZ ? |  6 | 1390090875 | 
|  164 | 233 | 3IHU1YKK ? |  9 | 1416089612 | 
|   59 | 296 | 8MJCWR55 ? |  3 | 1420850554 | 
|   75 | 268 | 2G4G42WW ? |  16 | 1427431541 | 
+------------+-----+------------+----------+-------------+ 
51 rows in set (0.01 sec) 

究其原因,其他的答案似乎返回相同的問題(前3名或底部3)IMO是因爲表的物理順序的,這就是我創建第二張表的原因。第二張表使用新的虛假物理順序,並通過隨機順序插入(因此物理順序問題不存在)。希望這是有道理的。

當然,我從pjanaway偷走了答案,雖然我喜歡他的變量方法,但無法讓Gordon在我的系統上工作。

祝你好運。

+0

這也是一個很酷的解決方案。 thx和投票了。 –

相關問題