2010-01-20 65 views
2

我试图运行的SQLite 3以下查询:故障使用SQLite SQL查询

SELECT *, 
    DISTANCE(latitude, longitude, ?, ?) AS "distance" 
FROM "country" 
WHERE "id" NOT LIKE ? 
HAVING "distance" <= ? 
ORDER BY "distance" ASC; 

,但我得到了以下错误:

SQLSTATE[HY000]: General error: 1 a GROUP BY clause is required before HAVING

我不明白为什么要的SQLite我组的结果,但我仍然尝试了以下内容:

SELECT *, 
    DISTANCE(latitude, longitude, ?, ?) AS "distance" 
FROM "country" 
WHERE "id" NOT LIKE ? 
GROUP BY "id" 
HAVING "distance" <= ? 
ORDER BY "distance" ASC; 

而且我也试过这样:

SELECT *, 
    DISTANCE(latitude, longitude, ?, ?) AS "distance" 
FROM "country" 
WHERE "id" NOT LIKE ? 
GROUP BY "distance" 
HAVING "distance" <= ? 
ORDER BY "distance" ASC; 

没有错误,但所有记录都被返回(即使是那些有"distance" > ?)。我也试过:

SELECT *, 
    DISTANCE(latitude, longitude, ?, ?) AS "distance" 
FROM "country" 
WHERE "id" NOT LIKE ? 
    AND "distance" <= ? 
ORDER BY "distance" ASC; 

同样的输出,所有的记录都被返回。我已经加倍检查 - 距离正确计算...我不知道这个查询有什么问题,有人可以帮我吗?

回答

2

,而不必指定GROUP BY子句您不能指定HAVING条款。用途:

SELECT *, 
     DISTANCE(latitude, longitude, ?, ?) AS dist 
    FROM COUNTRY c 
    WHERE c.id NOT LIKE ? 
    AND DISTANCE(c.latitude, c.longitude, ?, ?) <= ? 
ORDER BY dist; 

如果您不想打电话距离超过一次,你可以使用子查询:

SELECT x.* 
    FROM (SELECT c.*, 
       DISTANCE(latitude, longitude, ?, ?) AS dist 
      FROM COUNTRY c 
      WHERE c.id NOT LIKE ?) x 
    WHERE x.dist <= ? 
ORDER BY dist; 
+0

但我曾尝试指定一个“GROUP BY”子句......有没有什么办法可以运行查询,而无需调用两次'DISTANCE'函数?这会使查询运行速度更快。 – 2010-01-20 05:03:27

+0

Hummm ...我不是嵌套查询的忠实粉丝,http://www.arubin.org/files/geo_search.pdf的第8页更直截了当。 MySQL手册(http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html)说:“SQL标准不允许HAVING子句命名任何未找到的列在GROUP BY子句中,如果它不包含在聚合函数中“。这是SQLite的特定?对不起,成为一个PITA,但有任何其他方式来解决这个问题? – 2010-01-20 05:14:00

+0

@Alix:没有任何其他选项可以最大限度地减少使用“DISTANCE”的次数。 DISTANCE不是一个聚合函数,所以比较属于'WHERE'子句。使用'HAVING'的唯一原因是因为你实际上是将记录分组 - 这对于一个国家的表来说不太可能。 – 2010-01-20 05:23:34

0

是语法错误,你必须有“按组”,当你使用具有事业使用,

您与组查询的是获取有记录(“距离”>),因为,有数据库规则首先它需要具有匹配记录的数据,然后在它通过有原因过滤记录之后它将执行分组。所以你永远不会有数据(“距离” <)

请纠正,如果我错

+0

谢谢,我不知道。有什么方法可以重写查询,以便它只返回具有'distance <=?'的记录,而不必调用两次'DISTANCE'函数? – 2010-01-20 05:07:30

1

一个更好的(和更快)的方式可能是减少停机选定的一组在应用ORDER BY之前。我用这样的方法:

SELECT * FROM位置WHERE ABS(纬度 - 51.123)< 0.12和ABS(经度 - 0.123)< 0.34 ORDER BY DISTANCE(纬度,经度51.123,0.123)

。 ..其中(51.123,0.123)是您正在搜索的中心纬度/经度点,0.12和0.34的值用于将搜索范围缩小为一个经纬度的经纬度适当的大小(即在地球球面上的那个点上的n公里乘以n的平方,其大小取决于你的位置的平均地理分布)。我使用http://en.wikipedia.org/wiki/Longitude的度数长度公式来计算出这些值应该赋予搜索点在地球球面上的位置。

+0

谢谢。我这样做,我只是没有发布,以避免添加太多混乱。 =) – 2010-01-20 22:06:37

-2

而且正确的标记回答上面的,如果你不想调用距离函数两次,请参阅别名WHERE子句中,即:

SELECT *, 
     DISTANCE(latitude, longitude, ?, ?) AS dist 
    FROM COUNTRY c 
    WHERE c.id NOT LIKE ? 
    AND dist <= ? 
ORDER BY dist; 
+0

看看我的问题的最后一个代码片段... – 2010-02-22 19:49:22