这是我当前的查询:
SELECT questions.question, questions_headings.title FROM questions JOIN questions_headings ON questions.heading=questions_headings.id WHERE questions.heading IN (1,2,3) ORDER BY RANDOM() LIMIT 10
基本上,数据库包含各种标题的问题。例如:
questions_headings:
+----+-------+
| id | title |
+----+-------+
| 0 | blah1 |
+----+-------+
| 1 | lol1 |
+----+-------+
| 2 | etc1 |
+----+-------+
questions:
+----+---------+----------+
| id | heading | question |
+----+---------+----------+
| 0 | 1 | howdoi |
+----+---------+----------+
| 1 | 0 | blahques |
+----+---------+----------+
| 2 | 1 | herro |
+----+---------+----------+
我的查询所做的是从给定标题中随机选择X个问题并将其显示给用户。
目前,如果您想要10个随机问题(LIMIT 10),它会在所有ID中提供10个随机问题。正常,对吗?但我不想要这个。
我需要查询做的是,提取分布在给定ID上的10个随机问题。这样,我不会从一个标题中得到9个问题而从另一个标题收到1个问题。
希望有意义......
是否可以仅使用SQL执行此操作?
答案 0 :(得分:0)
如果您在创建查询时知道标题,则可以执行以下操作:
SELECT * FROM (
SELECT questions.question, questions_headings.title FROM questions JOIN questions_headings ON questions.heading=questions_headings.id WHERE questions.heading = 1 ORDER BY RANDOM() LIMIT 3
UNION
SELECT questions.question, questions_headings.title FROM questions JOIN questions_headings ON questions.heading=questions_headings.id WHERE questions.heading = 2 ORDER BY RANDOM() LIMIT 3
UNION
SELECT questions.question, questions_headings.title FROM questions JOIN questions_headings ON questions.heading=questions_headings.id WHERE questions.heading = 3 ORDER BY RANDOM() LIMIT 3
UNION
SELECT questions.question, questions_headings.title FROM questions JOIN questions_headings ON questions.heading=questions_headings.id WHERE questions.heading IN (1,2,3) ORDER BY RANDOM() LIMIT 10
) LIMIT 10
这个想法是,从每个标题获得10/3 = 3,然后从所有标题中获取剩余部分(因为舍入错误)。因为最后一个查询可能导致已经获取的数据,我们限制为10,所以我们肯定得到我们需要的额外1,然后再次限制整个事情。 应该导致均匀分布的值。
答案 1 :(得分:0)
以下内容适用于DB2(可以轻松移植到支持row_number的其他数据库):
SELECT * FROM (
SELECT question, title
FROM (
SELECT questions.question, questions_headings.title,
row_number() over(PARTITION BY questions.headings ORDER BY rand()) rn
FROM questions JOIN questions_headings ON questions.heading=questions_headings.id
WHERE questions.heading IN (1,2,3)
)
WHERE rn <= 3
UNION
SELECT questions.question, questions_headings.title
FROM questions JOIN questions_headings ON questions.heading=questions_headings.id
WHERE questions.heading = 1
ORDER BY RAND()
FETCH FIRST 10 ROWS ONLY
)
FETCH FIRST 10 ROWS ONLY
答案 2 :(得分:0)
这适用于PostgreSQL:
SELECT q2.row - (SELECT count(*)
FROM questions q3
WHERE q3.heading IN (1, 2, 3)
AND q3.heading < q2.heading) AS ord,
q2.heading, q2.question
FROM (
SELECT row_number() OVER (ORDER BY heading, random()) as row,
q1.id, q1.heading, q1.question
FROM questions q1
WHERE heading IN (1,2,3)
ORDER BY heading, row) AS q2
ORDER BY ord
LIMIT 10;
我无法测试MySQL版本,但这可能有用:
SELECT q2.row - (SELECT count(*)
FROM questions q3
WHERE q3.heading IN (1, 2, 3)
AND q3.heading < q2.heading) AS ord,
q2.heading, q2.question
FROM (
SELECT @rownum:=@rownum+1 AS row,
q1.id, q1.heading, q1.question
FROM questions q1, (SELECT @rownum:=0) r
WHERE heading IN (1,2,3)
ORDER BY heading, rand()) AS q2
ORDER BY ord
LIMIT 10;
重点是对记录进行排序,以便在来自任何选定标题的第二个问题之前,每个选定标题中只有一个问题,依此类推。如果对某些标题没有足够的问题,它仍将平均分配给其他标题。