sql - MySQL 查询动态范围?

标签 sql mysql

给定表格片段:

id | name | age

我正在尝试构建一个查询,该查询将返回特定年龄范围内的 10 个人。但是,如果那个范围内没有足够的人,我想扩大范围,直到我能找到 10 个人。

例如,如果我只找到 30-40 岁之间的 5 个人,我会找到 25-45 岁之间的另外 5 个人。

此外,我希望查询能够使用 RAND() 或类似命令,以便每次都能获得不同的结果。

这是否超出了 MySQL 的处理能力?我是否必须改为将其中的一些逻辑放入应用程序中?

最佳答案

性能更新:

我最初的解决方案有效,但需要进行表扫描。 Am 的解决方案是一个很好的解决方案,不需要表扫描,但是当唯一的匹配项是非常异常值时,它的硬编码范围将不起作用。此外,它还需要删除重复记录。但是,将这两种解决方案结合起来可以让您两全其美,前提是您有一个关于年龄的索引。 (如果您没有年龄索引,那么所有解决方案都需要进行表扫描)。

组合解决方案首先仅选择可能符合条件的行(所需范围,加上超出该范围的 10 行和低于该范围的 10 行),然后使用我的原始逻辑对结果进行排名。警告:我没有足够的样本数据来验证 MySQL 的优化器确实足够聪明,可以避免此处的表扫描——MySQL 可能不够聪明,无法在不进行扫描的情况下将这三个 UNION 编织在一起。

[刚刚再次更新以修复 2 个令人尴尬的 SQL 拼写错误:DESC 不应该出现的地方!]

SELECT * FROM
(
  SELECT id, name, age,
     CASE WHEN age BETWEEN 25 and 35 THEN RAND() ELSE ABS (age-30) END as distance
  FROM
  (
     SELECT * FROM (SELECT * FROM Person WHERE age > 35 ORDER BY age DESC LIMIT 10) u1
     UNION
     SELECT * FROM (SELECT * FROM Person WHERE age < 25 ORDER BY age LIMIT 10) u2
     UNION
     SELECT * FROM (SELECT * FROM Person WHERE age BETWEEN 25 and 35) u3
  ) p2
  ORDER BY distance
  LIMIT 10
) p ORDER BY RAND() ;

原始解决方案:

我会这样处理:

  1. 首先,计算每条记录与所需年龄范围中心的距离,然后按该距离对结果进行排序。对于范围内的所有结果,将距离视为介于 0 和 1 之间的随机数。这确保范围内的记录将以随机顺序被选择,而范围外的记录将在需要时以最接近所需范围的顺序被选择。
  2. 将按距离排序的结果集中的记录数减少为 10 条记录
  3. 随机生成记录的顺序

像这样:

CREATE TABLE Person (id int AUTO_INCREMENT PRIMARY KEY, name varchar(50) NOT NULL, age int NOT NULL);
INSERT INTO Person (name, age) VALUES ("Joe Smith", 26);
INSERT INTO Person (name, age) VALUES ("Frank Johnson", 32);
INSERT INTO Person (name, age) VALUES ("Sue Jones", 24);
INSERT INTO Person (name, age) VALUES ("Ella Frederick", 44);

SELECT * FROM
(
  SELECT id, name, age,
     CASE WHEN age BETWEEN 25 and 35 THEN RAND() ELSE ABS (age-30) END as distance
  FROM Person
  ORDER BY distance DESC
  LIMIT 10
) p ORDER BY RAND() ;

请注意,我假设如果范围内没有足够的记录,则您要追加的记录是最接近该范围的记录。如果此假设不正确,请在问题中添加更多详细信息。

re: 性能,这需要扫描整个表,所以不会很快——我现在正在研究一个无扫描的解决方案......

关于sql - MySQL 查询动态范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1777007/

相关文章:

mysql - 使用 MySQL 的查询中的查询

mysql - 子查询错误

mysql - 使用mysql中的其他表获取随机图像

mysql - 列表框 Laravel 数据

mysql - 如何在 mysql 中索引(或查看)两个表?

php - 在 SELECT 语句中返回嵌套的行数组?

mysql - SQL 显示空值分组依据

c# - SQL Azure 每 10 秒延迟响应一次

php - 使用 PHP 从 mysql 导出到 csv 时获取列名

MySQL:计算列中的宽度日期