繁体   English   中英

MySQL中的计数或条件限制

[英]Limit by count OR condition in MySQL

我正在制作一个使用地理位置的网络应用程序,我正在掀起一个“附近的地方”视图。 这是非常简单的逻辑:它显示了存储在数据库中的最近5个位置。 完善。

诀窍是我希望它返回最近的5个地方或两英里内的所有地方,以较大者为准。 换句话说,我希望用户能够至少看到两英里内的所有地方,但如果该半径内没有5个地方,我希望他们显示最接近的5个。

让我们将它们用于样本数据集。 第1组:

| id | name                 | distance  |
+----+----------------------+-----------+
| 3  | Earl of Sandwich     | 0.3       |
| 4  | Nails 'n More        | 0.8       |
| 22 | City Hotel           | 1.7       |
| 5  | Mighty Medicine      | 2.1       |
| 25 | Wonder Wings         | 2.5       |
| 6  | Jean Warehouse       | 2.7       |
| 9  | Ship Safe & Speedy   | 2.9       |
| 2  | Bagel Bonus          | 4.1       |
+----+----------------------+-----------+

第2集:

| id | name                 | distance  |
+----+----------------------+-----------+
| 3  | Earl of Sandwich     | 0.1       |
| 4  | Nails 'n More        | 0.2       |
| 5  | Mighty Medicine      | 0.5       |
| 6  | Jean Warehouse       | 0.7       |
| 9  | Ship Safe & Speedy   | 0.9       |
| 2  | Bagel Bonus          | 1.2       |
| 22 | City Hotel           | 1.7       |
| 25 | Wonder Wings         | 2.1       |
+----+----------------------+-----------+

在第一组中,我想要返回第3,4,25,5和25行。在第二组中,我想要显示3,4,5,6,9,2和22。

我知道我总是可以将查询限制在100个位置,并通过PHP中的结果集进行过滤...但我想知道是否有更有效的方法在SQL中正确执行。

总之,执行此操作的方法是运行两个查询并获取集合的UNION。 而已。 这样做的确很少有性能损失,因为如果结果中确实有超过5行,则已经需要第一组(可以产生> 5行)。

详细 - 原始答案如下

为了说明,我只使用同一样本表中的2列,而不是使用2个数据集,查询将在下面进一步显示:

drop table if exists tbl1;
create table tbl1 (
id int,
name varchar(100),
distance1 float,
distance2 float
);
insert tbl1 values
( 3  , 'Earl of Sandwich   ', 0.3, 0.1),
( 4  , 'Nails ''n More     ', 0.8, 0.2),
( 22 , 'City Hotel         ', 1.7, 1.7),
( 5  , 'Mighty Medicine    ', 2.1, 0.5),
( 25 , 'Wonder Wings       ', 2.5, 2.1),
( 6  , 'Jean Warehouse     ', 2.7, 0.7),
( 9  , 'Ship Safe & Speedy ', 2.9, 0.9),
( 2  , 'Bagel Bonus        ', 4.1, 1.2);

以及查询和结果:

/* query 1 */
select id, name, distance1
from (
    select *
    from tbl1
    where distance1 <= 2.0
    order by distance1) a
union
select id, name, distance1
from (
    select *
     from tbl1
    order by distance1
     limit 5) b;

/* result 1 */
id;name;distance1
3;Earl of Sandwich   ;0.3
4;Nails 'n More     ;0.8
22;City Hotel         ;1.7
5;Mighty Medicine    ;2.1
25;Wonder Wings       ;2.5

/* query 2 */
select id, name, distance2
from (
    select *
    from tbl1
    where distance2 <= 2.0
    order by distance2) a
union
select id, name, distance2
from (
    select *
     from tbl1
    order by distance2
     limit 5) b;

/* result 2 */
id;name;distance2
3;Earl of Sandwich   ;0.1
4;Nails 'n More     ;0.2
5;Mighty Medicine    ;0.5
6;Jean Warehouse     ;0.7
9;Ship Safe & Speedy ;0.9
2;Bagel Bonus        ;1.2
22;City Hotel         ;1.7

这个查询的性能和它一样好。
第一个UNION部分挑出了<2km的部分。 这是必要的,因为你想要所有的比赛。
下一部分选择前5名并假设你有一个索引,这是很容易收集的。 两个部分的组合(UNION)非常快。

如果是我,我会让您的查询返回按距离排序的所有位置。 然后在PHP中你可以跳到阵列中的第5位(这将是距离第5个最远的地方,因为你已经按距离订购了查询)并检查它是否在2英里内。 如果它然后返回前5个,如果没有则返回所有它们。

所以你的查询就是:

SELECT id, name, distance FROM places ORDER BY distance ASC
SELECT * FROM places ORDER BY distance ASC LIMIT 5

不管怎样,最近的地方都会先拉(按asc排序),所以没关系。

LIMIT是从数据库中提取的最大结果,因此用户获得的最大位置是5,可能更少但不是更多。

你可以肯定使用mysql限制(并鼓励)订单:

SELECT * FROM `table` ORDER BY `distance` ASC LIMIT 5;

“ASC”告诉查询以递增的方式(从最小到最高)对行进行排序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM