MySQL中的计数或条件限制

时间:2012-03-02 21:22:46

标签: mysql sql

我正在制作一个使用地理位置的网络应用程序,而我正在掀起一个“附近的地方”视图。这是非常简单的逻辑:它显示了存储在数据库中的最近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中正确执行。

4 个答案:

答案 0 :(得分:3)

总之,执行此操作的方法是运行两个查询并获取集合的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)非常快。

答案 1 :(得分:0)

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

所以你的查询就是:

SELECT id, name, distance FROM places ORDER BY distance ASC

答案 2 :(得分:0)

SELECT * FROM places ORDER BY distance ASC LIMIT 5

无论如何最近的地方都会被拉(按asc排序), 所以没关系。

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

答案 3 :(得分:0)

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

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

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