我有一个表我希望根据优先级和日期明智获取记录,我通过此查询得到
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
任何帮助,建议都将非常感谢。
答案 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只需要反转advenddat
和advpri
的位置:
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