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

时间:2011-11-28 18:14:01

标签: php mysql sql

我需要有关如何构建一个将根据条件返回5个结果的查询的帮助 在这5个结果中,如果在查询中指定,则必须始终显示其中一个记录。
其余的将随机选择。

我有表COUNTRY,CATEGORY,QUESTIONS
对于COUNTRY我有记录:加拿大,中国,法国,德国,日本,美国
对于CATEGORY我有记录:资本,地标,标志,语言

每个问题都根据CATEGORY和COUNTRY进行分类 现在,每当我选择一个国家时,我都想要一个带有CATEGORY“CAPITAL”的问题始终显示在结果上 因此,如果我选择FRANCE,则必须选择5个关于法国的问题,其中一个结果的类别为CAPITAL,其他4个是随机选择的。

我的解决方案是有2个问题,但我不知道它是否正确:

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

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

然后只是追加结果。
我也从某个地方听说过使用RAND()函数有一个缺点,因为它必须先对记录进行排序才能选择随机记录。因此,如果您有数千条记录,那么使用它是不好的 所以,如果有更好的方法来做到这一点,如果有人可以提供帮助,我会非常感激。
在此先感谢。

3 个答案:

答案 0 :(得分:2)

为什么不添加另一列来表明该行的优先级更高?

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

或者,如果有非常具体的条件,您可以像这样编码:

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

<强>更新

我一直在建议同样的解决方案。好的,我会尝试详细说明一下。 什么是最好的IMO,是在你的表中添加一个“粘性”列(在你的情况下是问题)。

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

然后将所需的问题标记为粘性(为此设置管理UI或仅自己运行原始查询)

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

然后选择这样的问题:

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

最好建立一个管理界面来指定哪些问题是粘性的,并在添加问题后运行它。这对频繁的选择很有帮助。如果经常添加新问题,那么最好将条件直接放入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;

答案 1 :(得分:1)

这与你所拥有的非常相似,但它对我来说很好看:

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

答案 2 :(得分:0)

另一种方法是查询中的CASE语句:

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

但我想做两个查询实际上更快。