1

我目前正在尝试从位置表中进行选择。结果应该是最近的位置,另外应该是距离至少 30 公里的位置。

所以我想做一个

SELECT * FROM locations WHERE (distance = minimumdistance OR distance > 30) AND some other parameters LIMIT 2

但是如果没有第二个选择,我就无法获得最小距离,该选择也具有所有其他参数,这将使语句非常长。

MIN(distance) 需要一个分组,但这会导致我只得到一个结果而不是 2...

有什么方法可以更简单地做到这一点吗?在语句中创建没有完整 WHERE 子句两次的语句。

目前是

SELECT * FROM locations WHERE (distance = (SELECT MIN(distance) FROM locations WHERE some other parameters ) OR distance > 30) AND some other parameters LIMIT 2

现在试着想象一下,如果有一些其他参数是一个很长的字符串,而距离是一个计算而不是一个静态表列,这会变得非常讨厌。

4

4 回答 4

2

如果您坚持在一个查询中执行此操作,那么这将按您的需要执行(更新为更标准)

SELECT

        -- this will have 2 records, 1 nearest and 1 with l.distance > 30
        d.*
FROM (
    SELECT 
        loc.*,
        -- this assumes locationID == the PK field, update as needed
        IF(loc.distance>30,@farLoc := loc.locationID,@nearLoc := loc.locationID) AS ignoreMe
    FROM locations AS loc,
    (
        SELECT @nearLoc := 0,@farLoc := 0
    ) AS v
    WHERE some other parameters
    ORDER BY loc.distance DESC 
) AS d
WHERE d.locationID IN (@nearLoc,@farLoc)

但真正简单的联合会做你应该在这种情况下使用的东西

(
    SELECT * FROM locations 
    WHERE some other parameters
    ORDER BY distance ASC 
    LIMIT 1
) UNION (
    SELECT * FROM locations 
    WHERE some other parameters
    AND distance > 30 
    ORDER BY distance ASC 
    LIMIT 1
)

语句是否“非常长”并不重要,只要它是有效的。如果其他参数是在脚本中生成的,那么维护就不会产生额外的开销,这将是最有效的方法。

于 2013-03-28T13:09:15.487 回答
1

你可以试试这个

    SELECT * FROM locations WHERE  some other parameters 
    HAVING  distance > 30
    OR distance = minimumdistance 
    LIMIT 2
于 2013-03-28T13:04:43.633 回答
0

我对这种方法并不感兴趣,但它应该可以在 MySQL 中使用:

select l.*
from (SELECT l.*, (@rn = @rn+1) as rn
      FROM locations l cross join
           (select @rn = 0)
      WHERE some other parameters
      order by distance
     ) l
where rn = 1 or distance > 30
limit 2

@rn 是一个跟踪行号的变量。在大多数其他数据库中,您会使用row_number(),但 MySQL 不支持。然后它选择第一行(最小距离)或大于 30 的行。如果最小值大于 30,那么您将获得两行。

在实践中,它将返回最接近 30 的值。

于 2013-03-28T13:40:04.403 回答
0

The result should be the closest location and additionally a location that is at least 30km distance away

这在 mySQL 中有效吗?它适用于 SQLite:

     select min(distance) from foo
     where distance > (select min(distance) from foo) and distance > 30
     union 
     select min(distance) from foo 

如果它确实有效,您可以使用它来创建内联视图并执行以下操作:

     select name, min(dist) from
     (

     select name, dist
     from   foo
     join
     (
     select min(distance) as dist from foo 
     where distance > (select min(distance) from foo) and distance > 30
     union 
     select min(distance) as dist from foo  
     ) as X         
     on foo.distance = X.dist   

   )

   union

    select name, max(dist) from

    (

     select name, dist
     from   foo
     join
     (
     select min(distance) as dist from foo 
     where distance > (select min(distance) from foo) and distance > 30
     union 
     select min(distance) as dist from foo  
     ) as X         
     on foo.distance = X.dist   

   )

使用列 [distance] 上的索引,这将非常快。

于 2013-03-28T13:42:57.240 回答