根据优先级随机获取记录

时间:2013-07-22 11:18:47

标签: php mysql

我有一个表我希望根据优先级和日期明智获取记录,我通过此查询得到

  SELECT * 
    FROM tbadv 
   WHERE advstrdat < CURDATE() 
ORDER BY advenddat DESC,
         advpri=1 DESC,
         advpri=2 DESC,
         advpri=3 DESC,
         advpri=4 DESC,
         advpri=5 DESC 
   LIMIT 1

但是如果多条记录存在相同的优先级,那么我想从中随机记录。

告诉我在ORDER BY RAND()或使用JOIN之间我更喜欢哪个。

这些是我表中的一栏:

advid
advtit
advdes
advimg
advurl
advloc
advstrdat
advenddat
advpri

任何帮助,建议都将非常感谢。

2 个答案:

答案 0 :(得分:4)

目前还不清楚你想如何解决关系。

反正:

SELECT * 
   FROM tbadv 
   WHERE advstrdat < CURDATE() 
ORDER BY advenddat DESC, advpri BETWEEN 1 AND 5 DESC, advpri DESC, RAND()
   LIMIT 1

这将根据advenddat根据日期检索最新记录,无论优先级如何,即优先级较低的记录优先于较高优先级记录(因此,请检查{{1}是日期而不是日期时间,或者,如果是,则使用日期进行初始化。否则您只会很少拥有相同advenddat的记录,根据其他字段进行排序。

然后将选择优先级在1到5之间的记录。其中,优先级较高的人将先行。

如果两个记录在1到5之间具有相同的advenddat和相同的advenddat(比如说​​3),则会随机打破平局。

出于性能原因,您需要按此顺序在advpri上设置覆盖索引:

advstrdat, advenddat, advpri

如果表格很大且匹配很多记录,可以通过解耦记录选择(只需要主键)和实际记录检索来实现最佳性能:

CREATE UNIQUE INDEX tbadv_ndx ON tbadv ( advstrdat, advenddat, advpri, advid );

以上是一个大约有13万行的示例表,非常不平衡(所有记录都有效SELECT tbadv.* FROM tbadv JOIN ( SELECT advid FROM tbadv WHERE advstrdat < CURDATE() ORDER BY advenddat DESC, advpri BETWEEN 1 AND 5 DESC, advpri DESC, RAND() LIMIT 1 ) AS p USING ( advid ); +----+-------------+------------+--------+---------------+-----------+---------+-------+-------+-----------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+-----------+---------+-------+-------+-----------------------------------------------------------+ | 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | | | 1 | PRIMARY | tbadv | const | PRIMARY | PRIMARY | 4 | const | 1 | | | 2 | DERIVED | tbadv | range | tbadv_ndx | tbadv_ndx | 4 | NULL | 60924 | Using where; Using index; Using temporary; Using filesort | +----+-------------+------------+--------+---------------+-----------+---------+-------+-------+-----------------------------------------------------------+ ,所有记录都有效curdate等)。然而,它在几毫秒内完成。

“无效”记录会快速过滤,因此性能与单个查询的效果相同,只是检索到priority:此处只有七个记录匹配:

advid

不同的顺序

如果您希望+----+-------------+------------+--------+---------------+-----------+---------+-------+------+-----------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+-----------+---------+-------+------+-----------------------------------------------------------+ | 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | | | 1 | PRIMARY | tbadv | const | PRIMARY | PRIMARY | 4 | const | 1 | | | 2 | DERIVED | tbadv | range | tbadv_ndx | tbadv_ndx | 4 | NULL | 7 | Using where; Using index; Using temporary; Using filesort | +----+-------------+------------+--------+---------------+-----------+---------+-------+------+-----------------------------------------------------------+ 优先于advpri,即优先级为5的记录今天必须优先于优先级为4的记录,即使明年到期,您也可以d只需要反转advenddatadvpri的位置:

advenddat

现在优先级1-5先行,然后优先级为0,6,7,以及1-5之外的其他优先级;并且他们首先获得最高优先级(即5)。如果两个记录具有相同的优先级,那么具有较长预期寿命的记录将首先出现。只有当预期寿命相同时,选择才是随机的。 (您还必须在索引创建语句中交换字段位置)。

答案 1 :(得分:0)

SELECT * FROM tbadv where advstrdat<curdate() ORDER BY advenddat DESC, advpri DESC, RAND() DESC LIMIT 1