【问题标题】:Combining Multiple Mysql Queries组合多个 Mysql 查询
【发布时间】:2015-04-14 06:57:18
【问题描述】:

我有下表:

id  user_id  recorded      latitude      longitude   speed  note_type  details  image_url                           
1   10      3/29/2013    33.77701316   -84.39004377   -1       11       Test     2ecc2e36c3e1a512d349f9b407fb281e-2013-03-29-16-15-..

我正在尝试找到一种方法将以下查询组合成一个完整的查询,该查询将为我提供与每个单独查询匹配的所有记录(每个单独的查询都可以正常工作,只是无法弄清楚如何组合它们):

SELECT id, ( 3959 * acos( cos( radians(User_Input_Longitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(User_Input_Latitude) ) + sin( radians(User_Input_Longitude) ) * sin( radians( latitude ) ) ) ) AS distance 
FROM note HAVING distance < User_Input_Distance 
ORDER BY distance LIMIT 0 , 1000

SELECT details 
FROM note 
WHERE CHAR_LENGTH(details) > User_Input_CharacterLength

SELECT DISTINCT details 
FROM note;

SELECT DISTINCT image_url 
FROM note;

所以基本上我需要一个查询,将基于 long/lat 点的距离与用户定义的 long/lat 点和用户定义的距离进行比较,检查详细信息字段的字符长度,然后最后只记录具有不同数据的记录details 和 image_urls(很多 image_urls 和 details 都是空的,所以我一直在使用 distinct 来查找那些实际上有数据的人,不确定这是否是正确的方法)。

就像我之前说的,这些查询中的每一个现在都是单独工作的,但不幸的是我在 mySql 中没有足够的技能来以智能的方式组合它们。

任何关于这方面的建议都会很棒。

【问题讨论】:

  • HAVING distance &lt; User_Input_Distance 应该是 WHERE distance &lt; User_Input_Distance,对于初学者来说。除了你需要更新你的表架构,因为你需要执行一些joins,并且需要知道这些关系。
  • @lp_ 给出的答案涵盖了构建 MySQL 查询的正确方法。您可能还想考虑简化distance 子句,并简单地为“边界正方形”选择一个(可能)稍大的结果集,然后在您的 PHP 中拒绝不符合更精确极坐标的结果。这样可以减少 CPU 负载,还可以利用 longitudelatitude 列上的索引,尤其是在表很大的情况下。 HTH
  • @GavinJackson 好点。稍微澄清一下:你说做一个更简单的查询来检查距离,这基本上会占用更大的区域,然后在我的 php 文件过滤器中更接近以减少负载。有道理,因为我认为这个查询在计算上会很昂贵。我的表有大约 1k 个条目,但是“利用经度和纬度列上的索引”是什么意思?
  • @NASAIntern 目前我认为查询需要为每一行计算您的distance,因为如果不进行极坐标计算,它无法知道哪些行将符合中间HAVING条款。如果您根据“边界正方形”进行 SELECT,通过预先计算 max_lat、min_lat、max_lng、min_lng,作为“User_Latitude”、“User_Longitude”和“User_Distance”的函数,然后是(latitude BETWEEN (min_lat AND max_lat))AND(longitude BETWEEN min_lng AND max_lng ) 的 WHERE 子句如果纬度和经度列被索引,则只需要读取符合条件的行。

标签: php mysql


【解决方案1】:

虽然没有提供schema,但好像只有一张表。也许这就是你想要做的:

SELECT id, ( 3959 * acos( cos( radians(User_Input_Longitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(User_Input_Latitude) ) + sin( radians(User_Input_Longitude) ) * sin( radians( latitude ) ) ) ) AS distance, details, image_url
FROM note
WHERE ( 3959 * acos( cos( radians(User_Input_Longitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(User_Input_Latitude) ) + sin( radians(User_Input_Longitude) ) * sin( radians( latitude ) ) ) ) < User_Input_Distance
  AND CHAR_LENGTH(details) > User_Input_CharacterLength
  AND (details IS NOT NULL AND details<>'')
  AND (image_url IS NOT NULL AND image_url<>'')
ORDER BY distance LIMIT 0, 1000

一些注意事项:

  • 在没有group by 子句的情况下使用having 子句并不是在查询中使用条件的好方法,通常应该使用where 代替(见下文)。
  • 你说image_urldetails很多都是空的,你可以用is not null来检查它们是否为NULL。如果您也想过滤空字符串,请添加例如details&lt;&gt;'' and image_url&lt;&gt;'' 到 where 条件。
  • 此查询将结合您的所有条件,因此它将仅选择所有条件都匹配的那些记录,如果这不是您想要的,您可以使用or 来分离某些条件而不是它们连词。

[编辑]

MySQL(也作为标准 SQL)不允许在 WHERE 子句中引用列别名(参见 manual)。因此,您要么重复完整的表达式以计算其中的 distance,要么使用 HAVING 子句(此处应产生相同的结果,但方式略有不同)。

SELECT id, ( 3959 * acos( cos( radians(User_Input_Longitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(User_Input_Latitude) ) + sin( radians(User_Input_Longitude) ) * sin( radians( latitude ) ) ) ) AS distance, details, image_url
FROM note
HAVING distance < User_Input_Distance
  AND CHAR_LENGTH(details) > User_Input_CharacterLength
  AND (details IS NOT NULL AND details<>'')
  AND (image_url IS NOT NULL AND image_url<>'')
ORDER BY distance LIMIT 0, 1000

它可以工作,因为在HAVING 中您可以引用别名,但是在没有GROUP BY 的情况下使用它并不是真正正确使用SQL,它也可能会影响性能。您可以阅读更多关于 havingwhere herehere 的信息。

【讨论】:

  • 嘿,谢谢,这看起来不错。是的,这一切都来自一张桌子,所以我认为我不需要做任何连接。由于空字符串,NOT NULL 也不起作用。因此,您是说将 (and details'') 添加为单独的语句,还是仅与 NOT NULL 的同一行组合?同样在这种情况下,查询出现的顺序是否重要?如果距离排在第三位或最后,会发生什么?这样写是不是基本一个接一个过滤?
  • 我用&lt;&gt;''检查编辑了帖子中的查询,where clause'表示选择行必须满足的条件或条件',所以如果你指定更多的连接条件, RDBMS 将选择满足所有条件的记录。
  • 嘿,我在 WHERE 距离线上遇到错误。它的说法距离不是一个列名,这是真的。我删除了它,其他一切正常。
  • "#1054 - 'where 子句'中的未知列'distance'"
  • 我将 WHERE 距离更改为 HAVING 距离,它似乎有效。不知道为什么我需要更多地阅读这些命令的功能。我对mysql有非常基本的了解,需要升级...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-04
  • 1970-01-01
相关资源
最近更新 更多