简体   繁体   English

需要帮助来构造具有某个结果+随机结果的查询

[英]need help to construct a query with one certain result + random result

I need help on how to construct a query that will return 5 results based on a condition. 我需要有关如何构造将根据条件返回5个结果的查询的帮助。
And in those 5 results, one of the records must always appear if specified on the query. 在这5个结果中,如果在查询中指定了记录,则其中之一必须始终出现。
The rest will be randomly selected. 其余的将被随机选择。

I have the tables COUNTRY, CATEGORY, QUESTIONS 我有表格COUNTRY,CATEGORY,QUESTIONS
For COUNTRY I have the records: CANADA, CHINA, FRANCE, GERMANY, JAPAN, USA 对于国家,我有记录:加拿大,中国,法国,德国,日本,美国
For CATEGORY I have the records: CAPITAL, LANDMARKS, FLAG, LANGUAGE 对于CATEGORY,我有以下记录:大写,地标,标志,语言

Each question is categorized based on CATEGORY and COUNTRY. 每个问题都根据CATEGORY和COUNTRY进行分类。
Now I want a question with CATEGORY "CAPITAL" to always appear on the results whenever I select a country. 现在,我希望每当选择一个国家时,类别“ CAPITAL”中的一个问题就始终出现在结果中。
So if I select FRANCE, 5 questions ABOUT FRANCE must be selected where one of the result has the category CAPITAL and the other 4 are randomly selected. 因此,如果我选择FRANCE,则必须选择5个关于法国的问题,其中一个结果的类别为CAPITAL,其他4个是随机选择的。

my solution is to have 2 questions but I don't know if it's correct: 我的解决方案是有两个问题,但我不知道这是否正确:

SELECT * FROM QUESTIONS WHERE COUNTRY = "FRANCE" AND CATEGORY = "CAPITAL"

and

SELECT * FROM QUESTIONS WHERE COUNTRY = "FRANCE" AND CATEGORY != "CAPITAL" ORDER BY RAND() LIMIT 4

then just append the results. 然后只需附加结果即可。
I have also heard from somewhere that using the RAND() function has a downside on it because it must sort the records before before it can pick random records. 我也从某个地方听说过使用RAND()函数有一个缺点,因为它必须先对记录进行排序才能选择随机记录。 So it is not good to use if you have thousands of records. 因此,如果您有成千上万的记录,则不好用。
So if there is a better way to do this and if anyone could help, I would appreciate it a lot. 因此,如果有更好的方法可以做到这一点,并且任何人都可以提供帮助,我将不胜感激。
Thanks in advance. 提前致谢。

Why not just add another column to indicate that row is higher priority? 为什么不添加另一列来表明该行具有更高的优先级?

Select * from Colors order by priority DESC, Rand() limit 5

Or if there are very specific conditions, you can code them like this: 或者,如果有非常具体的条件,您可以像这样编码:

SELECT * FROM Colors
ORDER BY IF(ColorName = 'Green', 100, IF(_other_conds_if_any_, 99, 0)) DESC,
    Rand()
LIMIT 5

Update 更新

I keep suggesting the same solution. 我一直在建议同样的解决方案。 Ok, I'll try to elaborate a bit more. 好的,我会尝试详细说明。 What is best IMO, is to add a column "sticky" to your table (in your case that would be QUESTIONS). 最好的IMO是在表中添加一列“粘滞”(在您的情况下为QUESTIONS)。

ALTER TABLE `QUESTIONS` ADD COLUMN `sticky` TINYINT NOT NULL DEFAULT 0;

Then mark needed questions as sticky (make admin UI for that or just run raw query yourself) 然后将需要回答的问题标记为粘性(为此创建管理界面,或者自己运行原始查询)

UPDATE `QUESTIONS` SET `sticky` = IF(`CATEGORY` = "CAPITAL", 1, 0);

And then select your questions like this: 然后选择这样的问题:

SELECT *
FROM `QUESTIONS`
WHERE `COUNTRY` = "FRANCE"
ORDER BY `sticky` DESC, RAND()
LIMIT 5;

It would be best to make an admin UI to specify conditions on what questions are sticky, and run it after adding a question too. 最好使一个管理UI来指定关于哪些问题属于粘性的条件,并在添加一个问题后再运行它。 It is good for frequent selections. 非常适合经常选择的人。 If new questions are being added frequently then it would be better to put the condition directly into ORDER clause (no need to add that column then), or add the column to category table instead and JOIN it. 如果经常添加新问题,那么最好将条件直接放入ORDER子句中(不需要再添加该列),或者将列添加到类别表中并加入它。

#1. don't add any column and put condition into ORDER clause
SELECT *
FROM `QUESTIONS`
WHERE `COUNTRY` = "FRANCE"
ORDER BY IF(`CATEGORY` = "CAPITAL", 1, 0) DESC, RAND()
LIMIT 5;

#2. add column to categories table
SELECT q.*
FROM `QUESTIONS` q
    INNER JOIN `CATEGORIES` cat ON (cat.`CATEGORY_NAME` = q.`CATEGORY`)
    #unsure what your conditions would be here as Idon't know your DB structure
WHERE q.`COUNTRY` = "FRANCE"
ORDER BY cat.sticky DESC, RAND()
LIMIT 5;

This is very similar to what you have, but it looks fine to me: 这与你的非常相似,但对我来说看起来很好:

Select * from Colors where ColorName = 'Green'
UNION
SELECT * FROM (Select * from Colors where ColorName != 'Green' order by Rand() limit 4)

Another way would be a CASE statement in your query: 另一种方法是查询中的CASE语句:

SELECT *,
  CASE ColorName
    WHEN 'green' THEN 2
    ELSE RAND()
  END AS r
FROM Colors ORDER BY r DESC LIMIT 5

But I guess that doing two queries is actually faster. 但是我想执行两个查询实际上更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM