目前还不太清楚你想如何解决关系。
反正:
SELECT *
FROM tbadv
WHERE advstrdat < CURDATE()
ORDER BY advenddat DESC, advpri BETWEEN 1 AND 5 DESC, advpri DESC, RAND()
LIMIT 1
这将根据日期检索最新的记录advenddat
,而不考虑优先级,即比高优先级记录更新的低优先级记录将首先出现(因此,检查这advenddat
是一个日期而不是日期时间,或者,如果它是,它是用date初始化的。否则你只会很少有相同的记录advenddat
,要根据其他字段进行排序)。
然后将选择优先级在 1 到 5 之间的那些记录。其中,优先级高的优先。
如果两条记录在 1 和 5 之间有相同advenddat
的和相同的advpri
(比如 3),那么平局将被随机打破。
出于性能原因,您将希望按advstrdat, advenddat, advpri
以下顺序设置覆盖索引:
CREATE UNIQUE INDEX tbadv_ndx ON tbadv ( advstrdat, advenddat, advpri, advid );
如果表很大,并且匹配了许多记录,则可以通过将记录选择(只需要主键)和实际记录检索解耦来实现最佳性能:
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 |
+----+-------------+------------+--------+---------------+-----------+---------+-------+-------+-----------------------------------------------------------+
上面是一个包含大约 13 万行的示例表,非常不平衡(所有记录都有 valid curdate
,所有记录都有 validpriority
等)。然而,它在几毫秒内完成。
“无效”记录被快速过滤,因此性能等同于单个查询,除了只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
优先于advenddat
,即今天到期的优先级为 5 的记录必须优先于优先级为 4 的记录,即使它明年到期,你只需要反转advpri
and的位置advenddat
:
ORDER BY advpri BETWEEN 1 AND 5 DESC, advpri DESC, advenddat DESC, RAND()
现在优先级 1-5 优先,然后是优先级 0、6、7 和 1-5 范围之外的其他优先级;他们首先获得最高优先级(即5)。如果两条记录具有相同的优先级,则预期寿命较长的记录优先。只有当预期寿命相同时,选择是随机的。(您还必须在索引创建语句中交换字段位置)。