【问题标题】:Having a bit of trouble with MySQL query to receive random combinations from 3 tablesMySQL 查询从 3 个表中接收随机组合时遇到了一些麻烦
【发布时间】:2011-09-25 02:40:33
【问题描述】:

这是最初的问题:

好的,这是我的问题,我有两个 表,一个命名的名字和 其他命名的姓氏。我是什么 在这里尝试做的是找到100个 这些可能的组合 测试数据的名称。名字 表中有 5494 个条目 列,并且 lastnames 表有 单列中有 88799 个条目。这 唯一能查询到的 想出有一些结果的是:

SELECT * FROM
    (SELECT * FROM firstnames ORDER BY rand()) f
    LEFT JOIN
         (SELECT * FROM lastnames 
ORDER BY rand()) l ON 1=1 limit 10;    The problem with this code is

它选择 1 个名字并给出 每个可以与之搭配的姓氏。 虽然这是合理的,但我会有 将限制设置为 500000000 为了得到所有的组合 可能没有只有 20 首 名字(我宁愿不杀我的 服务器)。但是,我只需要 100 随机生成的条目 测试数据,我将无法 用这段代码得到它。任何人都可以 请给我一些建议?

  • 上面的问题已经回答了,我需要关于下面问题的建议。我只是提供它作为背景。

我想将另一个表加入到名为 status 的组合中。该表在一列中有 5 个条目,每当我尝试将其连接到另外两个时,它最终都会再次重复另外两个表,以便状态标签适合它们中的每一个。我唯一获得轻微成功的是:

SELECT *
FROM ( SELECT firstnames FROM firstnames ORDER BY RAND( )  LIMIT 5 ) AS First
JOIN ( SELECT lastnames FROM lastnames ORDER BY RAND( )  LIMIT 5 ) as Last 
JOIN ( SELECT status FROM status ORDER BY RAND( ) LIMIT 1) AS Status ON 1=1;

虽然名字和姓氏在此查询中不重复,但每个名字都只列出一个状态标签。非常感谢你们的帮助!

【问题讨论】:

标签: mysql join random limit


【解决方案1】:

使用 MySQL 变量,您应该能够通过类似...虽然没有经过明确测试,但这应该可以满足您的需求。你不能做一个简单的笛卡尔交叉连接,因为你知道它会得到第一个名字并加入所有姓氏,然后是下一个名字和所有姓氏......

此查询使用 MySQL 变量。内部查询(分别为名字和姓氏)将预先查询您的随机 10 个名字(或姓氏)。然后,将其连接到名字序列 (@fns) 和姓氏序列 (@lns) 的 @variable。由于两者都只有 10 条记录,并且每条记录的计数器都从 0 开始,因此它们都将产生序列为 1-10 的记录,因此 JOIN 将在 SEQUENCE 上,其中每个保证值中只有一个会出现... vs rand() 它返回一些浮点分数,你永远不能保证一个表中的数字与另一个表中的数字匹配。

select
      First10.FirstName,
      Last10.LastName,
      ( SELECT status FROM status ORDER BY RAND( ) LIMIT 1) AS Status
   from 
      ( select fn.FirstName,
               @fns := @fns + 1 as Sequence
           from
             ( select FirsName,
                  from FirstNames
                  order by rand() 
                  limit 10 ) fn,
             (select @fns := 0 ) vars
      ) First10

      JOIN

      ( select ln.LastName,
               @lns := @lns + 1 as Sequence
           from
              ( select LastName,
                   from LastNames
                   order by rand() 
                   limit 10 ) ln,
              (select @lns := 0 ) vars 
      ) Last10

      ON First10.Sequence = Last10.Sequence

【讨论】:

  • 这对于我上一个问题所需的原始查询要好得多。非常感谢!但是,现在我需要将该状态表添加到组合中。
  • @ypercube,谢谢...我发现 MySQL 变量对许多解决方案都很方便...并且已用于 S/O 提供的各种 COMPLEX 解决方案。跨度>
  • @michael;最后加上JOIN ( SELECT status FROM status ORDER BY RAND() LIMIT 1) AS Status。然后所有 100 行将具有相同的(随机)状态。
  • @Michael,只需将其添加为 FIELD 级别的选择(因为我已经更新了答案)
  • 知道了,你们帮了很多忙。你有我的感激:)
【解决方案2】:

这应该可以解决状态问题:

SELECT
    First.firstnames firstname
    Last.lastnames lastname
    ( SELECT status FROM status ORDER BY RAND() LIMIT 1 ) status
FROM 
    ( SELECT firstnames FROM firstnames ORDER BY RAND()  LIMIT 5 ) First
    JOIN ( SELECT lastnames FROM lastnames ORDER BY RAND()  LIMIT 5 ) Last

【讨论】:

    【解决方案3】:

    我不知道你的状态表是做什么的,但这会给你随机的名字:

    select firstnames, lastnames
    from (select firstnames from firstnames order by rand() limit 100) fn
    cross join (select lastnames from lastnames order by rand() limit 100) ln
    order by rand()
    limit 100;
    

    别名选择在那里,因此查询在此生命周期内返回 - 交叉连接中有 10000 行......可管理。没有它们,就会有无数行 - 查询不会返回您的行数

    【讨论】:

    • 状态表旨在通过标签随机标记随机名称。例如。 Alive、Dead 等。总共有 5 行。
    【解决方案4】:

    把它转过来怎么样:

    SELECT f.name,l.name FROM lastnames l INNER JOIN firstnames f ON 1=1 ORDER BY rand() limit 100;
    

    内连接比左连接等快?

    【讨论】:

    • 查询再也没有回来,我已经有了这部分问题的解决方案。我正在尝试将状态表加入其他两个。
    • 向这个查询添加状态会比使用子选择更简单
    • 在执行ORDER BY RAND()之前,它将尝试在内存中创建两个表的CROSS JOIN。在这种情况下,这意味着 500M 行。
    【解决方案5】:

    我将首先在两个表上添加一个(自动生成的)id 字段。

    然后我会写一个存储过程:

    • 创建一个临时表 randomid,其中包含 2 个字段(firstid、lastid)。

    • 在两个字段中插入 100 行(或您需要的数字)和随机整数,(从 1 到 MAX(firstnames.id) 到第一个字段,从 1 到 MAX(lastnames.id) 到第二个)。

    • firstnameslastnames 表加入randomid

    • 删除临时表。

    【讨论】:

    • 我已经有了生成随机名称的解决方案,但我需要将状态表加入其他两个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    相关资源
    最近更新 更多