【问题标题】:Random row from random derived table随机派生表中的随机行
【发布时间】:2020-07-03 13:19:08
【问题描述】:

我有一组表,我想从其中一个随机表中选择一个随机行。

如果有 5 张桌子

Table1
Table2
Table3
Table4
Table5

每个都有相同的数据格式。

我尝试了以下方法,选择随机表的第一部分有效,但从表中获取信息返回 0 行。

 SELECT * FROM (SELECT `cat_table_name` from `category-defines` GROUP BY `cat_table_name` LIMIT 1) AS x ORDER BY RAND() LIMIT 3

【问题讨论】:

  • 为什么你有5张桌子?显然,这是一个有缺陷的设计。
  • 除了 Strawberry 所说的这种糟糕设计的味道之外,您可能还想对所有这些表进行 UNION 并从结果中随机选择一行。

标签: mysql


【解决方案1】:

并非每项任务都可以在单个 SQL 查询中完成。

在 SQL 中,所有表名(实际上是所有标识符)都必须在解析查询时固定。您不能编写一个 SQL 查询来根据查询期间评估的表达式来选择表(或列等)。

以此类推:就像在任何其他代码中一样,尝试调用一个名称基于您要调用的函数的返回值的函数。

所以你不能在一个查询中做你想做的事。

您可以在一个查询中选择随机表名,然后在您形成下一个查询时使用该结果。

SELECT `cat_table_name` from `category-defines` GROUP BY `cat_table_name` LIMIT 1

SELECT * FROM `$result_from_previous_query` ORDER BY RAND() LIMIT 3

这是最简单的解决方案。

请务必用反引号分隔您的表名,以防表名之一是 FROM 或其他一些 reserved keyword

(注意:上面的第一个查询不会选择 random 表名,它总是选择 first 表)。

上面的评论建议使用所有表的 UNION。这就是它的样子:

SELECT *
FROM 
(SELECT FLOOR(RAND()*5)+1 AS table_num) AS r
JOIN (
    (SELECT 1 AS table_num, * FROM my_table1 ORDER BY RAND() LIMIT 3)
    UNION
    (SELECT 2 AS table_num, * FROM my_table2 ORDER BY RAND() LIMIT 3)
    UNION
    (SELECT 3 AS table_num, * FROM my_table3 ORDER BY RAND() LIMIT 3)
    UNION
    (SELECT 4 AS table_num, * FROM my_table4 ORDER BY RAND() LIMIT 3)
    UNION
    (SELECT 5 AS table_num, * FROM my_table5 ORDER BY RAND() LIMIT 3)
) AS x USING (table_num) 

但这至少有两个问题:

  • 它承担了从 每个 表中选择随机行的性能成本,只是为了丢弃其中的大部分。浪费。
  • 您仍然需要提前知道表名,因此如果它们不固定,您最终会在此之前运行另一个查询以获取表名列表。

【讨论】:

    【解决方案2】:

    这是因为主查询将在派生表的结果(在本例中为表名)执行,而不是实际表名。

    就我的 MySQL 知识而言,您必须将其拆分为两个查询,其中第一个查询检索表名,第二个查询使用第一个查询的结果。在 PHP 中它看起来像这样

    //get a random table name
    $stmt = $this->pdo->prepare('SELECT `cat_table_name` as table from `category-defines` GROUP BY `cat_table_name` LIMIT 1');
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    
    //select 3 random rows with the table name
    $stmt = $this->pdo->prepare('SELECT * FROM '.$row['table'].' ORDER BY RAND() LIMIT 3');
    
    $stmt->execute();
    $randomRows = $stmt->fetchAll(PDO::FETCH_ASSOC); //the three random rows
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 2015-03-27
      • 1970-01-01
      • 2011-12-06
      相关资源
      最近更新 更多