【问题标题】:Getting random entries based off of category根据类别获取随机条目
【发布时间】:2023-04-05 00:41:02
【问题描述】:

我有一个名为“文章”的表。该表的结构如下:id(唯一),category(文章的类别,即娱乐),title(文章的标题),image(文章的图片URL),link(文章的URL文章)、Counter(文章的浏览量)、dateStamp(文章的发表日期)。

假设我想打印 6 篇随机娱乐文章。解决此问题的简单但效率较低的方法是执行类似

$result = $db->query("SELECT * FROM Articles WHERE category = 'entertainment' ORDER BY RAND() LIMIT 6);

相反,我该如何更有效地处理它?我知道有多个网站解释 ORDER BY RAND() 的替代方案,但我只是不理解这些替代方案。我想根据我的结构来理解。我尝试了多种方法,从改组关联数组到创建随机生成器,但都以失败告终,因为我无法让它正常工作。如何在不使用 ORDER BY RAND() 的情况下打印出 6 篇随机娱乐文章?

【问题讨论】:

  • 你的桌子大吗(比如说超过 1000 个条目)?如果没有,您可以选择所有数据,并使用 PHP 在结果中获取随机行...
  • @Random 现在不大,但是以后会变大的,所以我现在想要一个解决方案,这样就不用回去修了。

标签: php mysql mysqli


【解决方案1】:

没有通用的方法,一种有效的选择是根据给定的(可选)标准选择随机的子集数据,category 在您的情况下。请注意此列上添加的索引。

SELECT
    r1.*
FROM
    articles AS r1
    INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM articles)) AS id) AS r2
WHERE
    r1.id >= r2.id
    AND r1.category = 'entertainment'
LIMIT 6;

此处包含示例数据(320 万行)和执行计划的详细信息:

mysql> SELECT COUNT(*) FROM articles;
+----------+
| COUNT(*) |
+----------+
|  3200000 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT
    r1.*
FROM
    articles AS r1
    INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM articles)) AS id) AS r2
WHERE
    r1.id >= r2.id
    AND r1.category = 'entertainment'
LIMIT 6;
+---------+-------------+-----------------------------------------------------------+---------------+
| id      | topic       | message                                                   | category      |
+---------+-------------+-----------------------------------------------------------+---------------+
| 3153910 | JAX68VVH3FZ | Sed eu eros. Nam consequat dolor                          | entertainment |
| 3153911 | NIY23HWV0VM | tortor. Nunc commodo auctor velit. Aliquam nisl. Nulla eu | entertainment |
| 3153912 | LKQ42FRB7LA | mus. Proin vel nisl. Quisque                              | entertainment |
| 3153913 | PFL39VHI9RM | gravida                                                   | entertainment |
| 3153914 | FGV59TUN9TQ | elit, pellentesque a, facilisis non, bibendum sed,        | entertainment |
| 3153915 | OWH73EBZ1GW | ligula. Nullam enim. Sed nulla ante, iaculis              | entertainment |
+---------+-------------+-----------------------------------------------------------+---------------+
6 rows in set (0.473 sec)

mysql> explain extended 
SELECT
    r1.*
FROM
    articles AS r1
    INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM articles)) AS id) AS r2
WHERE
    r1.id >= r2.id
    AND r1.category = 'entertainment'
LIMIT 6;
+----+-------------+------------+--------+-----------------+---------+---------+-------+---------+----------+------------------------------+
| id | select_type | table      | type   | possible_keys   | key     | key_len | ref   | rows    | filtered | Extra                        |
+----+-------------+------------+--------+-----------------+---------+---------+-------+---------+----------+------------------------------+
|  1 | PRIMARY     | <derived2> | system | NULL            | NULL    | NULL    | NULL  |       1 |      100 | NULL                         |
|  1 | PRIMARY     | r1         | ref    | PRIMARY,cat_IDX | cat_IDX | 768     | const | 1560229 |      100 | Using index condition        |
|  2 | DERIVED     | NULL       | NULL   | NULL            | NULL    | NULL    | NULL  | NULL    | NULL     | No tables used               |
|  3 | SUBQUERY    | NULL       | NULL   | NULL            | NULL    | NULL    | NULL  | NULL    | NULL     | Select tables optimized away |
+----+-------------+------------+--------+-----------------+---------+---------+-------+---------+----------+------------------------------+
4 rows in set (0.00 sec)

在相同数量的数据下,性能差异比通常情况下显着(超过 10 倍):

mysql> SELECT * FROM articles WHERE category = 'entertainment' ORDER BY RAND() LIMIT 6;
+---------+-------------+---------------------------------------------------------------------------+---------------+
| id      | topic       | message                                                                   | category      |
+---------+-------------+---------------------------------------------------------------------------+---------------+
| 2374491 | PZC33VGM0ML | Duis cursus, diam at pretium aliquet, metus urna convallis erat,          | entertainment |
|  382306 | RFN88EPE4MI | malesuada fames ac turpis egestas. Aliquam fringilla cursus purus. Nullam | entertainment |
| 1867986 | KWX30ULB1FR | pede.                                                                     | entertainment |
| 1528863 | ADX52RRJ3MQ | lacus. Mauris non                                                         | entertainment |
| 2188208 | AOD82PXQ6FS | diam luctus lobortis. Class aptent taciti sociosqu ad litora              | entertainment |
|  878426 | ABV08HTB2PG | eu eros. Nam consequat dolor vitae dolor. Donec fringilla. Donec          | entertainment |
+---------+-------------+---------------------------------------------------------------------------+---------------+
6 rows in set (5.726 sec)

希望对你有所帮助。

【讨论】:

  • 感谢您的回答!我有一个问题,当你说 SELECT r1.* 时,r1 是什么?
  • 另外,我有 7 个娱乐条目。我希望准确显示 6 篇随机娱乐文章,此查询有时显示 4、5 等。数字 1-6。如果我想准确显示 6 篇文章,我会怎么做?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-22
  • 2011-12-18
  • 2019-02-27
相关资源
最近更新 更多