我正在使用a slightly-modified version of the geocoded gem,当我在我的模型上调用near
时调用Deal.near(southwest)
,其中southwest
是一个地理坐标数组):< / p>
SELECT
deals.*,
3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180 / 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat * PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() / 180 / 2), 2) )) AS distance,
CAST(DEGREES(ATAN2( RADIANS(addresses.lng - -122.42336332798004), RADIANS(addresses.lat - 37.772476604436974))) + 360 AS decimal) % 360 AS bearing
FROM "deals"
INNER JOIN "companies" ON "companies"."id" = "deals"."company_id"
INNER JOIN "addresses" ON "addresses"."addressable_id" = "companies"."id" AND "addresses"."addressable_type" = 'Company'
WHERE (
addresses.lat BETWEEN 37.483013038215276 AND 38.06194017065867
AND addresses.lng BETWEEN -122.78956461309022 AND -122.05716204286986
)
GROUP BY
deals.id,
deals.created_at,
deals.updated_at,
deals.active,
deals.company_id,
deals.title,
deals.limitations,
deals.redemption_count,
addresses.lat,
addresses.lng
HAVING 3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180 / 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat * PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() / 180 / 2), 2) )) <= 20
ORDER BY 3958.755864232 * 2 * ASIN(SQRT(POWER(SIN((37.772476604436974 - addresses.lat) * PI() / 180 / 2), 2) + COS(37.772476604436974 * PI() / 180) * COS(addresses.lat * PI() / 180) * POWER(SIN((-122.42336332798004 - addresses.lng) * PI() / 180 / 2), 2) )) ASC
我的问题是,如果Deal
的公司有多个Deal
es,这将返回多个Address
条记录,这是我不想要的。
在MySQL中,我可以省略address.lat, address.lng
子句中的GROUP_BY
,它会正确地对记录进行分组,但我不能在PostgreSQL中执行此操作。
我知道我可以将上面的整个查询包含在另一个SELECT
和GROUP_BY
中,如下所示:
SELECT
id, created_at, updated_at, active, title, punches_to_complete, company_id, description, lat, lng, MIN(distance), bearing
FROM ( ... ) AS t
GROUP BY company_id
...省略号是上面的查询。那(我相信)应该在MySQL和PostgreSQL中得到我想要的结果。
唯一的问题是我不知道如何在ARel中写这个!
我曾尝试过以下内容,来自AREL大师的la this tip,但我无法让它工作得很好(调用to_sql
,因为OP已经说过修复了他的问题逃脱了报价,这让PostgreSQL惹恼了。)
任何人都可以帮我这个???
的更新 :
我已经成功完成了另外一个范围,如下所示:
scope :nearest, lambda { |coords|
subquery = "(#{Deal.near(coords).to_sql}) AS t1"
columns = Deal.columns.map{ |c| c.name }.join(',')
Deal.select(columns)
.select('MIN(distance) AS distance')
.from(subquery)
.group(columns)
.order('distance ASC')
}
但是,这完全打破了可链接性,因为现在我无法调用类似current_user.deals.nearest(coords)
的内容,因为它会在子选择之外的其他WHERE deals.user_id = 1
上标记。我尝试通过将此逻辑移动到类方法并手动消除SelectManager上的wheres子句来补偿这一点,如下所示:
def self.nearest(coords)
subquery = "(#{Deal.near(coords).to_sql}) AS t1"
columns = Deal.columns.map{ |c| c.name }.join(',')
query = Deal.select(columns)
.select('MIN(distance) AS distance')
.from(subquery)
.group(columns)
.order('distance ASC')
query.arel.ast.cores[0].wheres = []
query
end
...但这似乎也不起作用:附加WHERE
子句仍然附加:
故障/错误: @ user.deals.nearest(southwest).first.distance.to_f.round(2).should == ActiveRecord的:: StatementInvalid: Mysql2 ::错误:'where'中的未知列'deals.user_id' 子句':SELECT id,created_at,updated_at,user_id,company_id, MIN(距离)AS距离FROM(SELECT deals。*,3958.755864232 * 2 * ASIN(SQRT(POWER(SIN)(37.772476604436974 - addresses.lat)* PI()/ 180 / 2),2)+ COS(37.772476604436974 * PI()/ 180)* COS(addresses.lat * PI()/ 180)* POWER(SIN(( - 122.42336332798004 - addresses.lng)* PI()/ 180/2),2)))AS距离,CAST(DEGREES(ATAN2(RADIANS(addresses.lng) - -122.42336332798004),RADIANS(addresses.lat - 37.772476604436974))) + 360 AS十进制)%360 AS来自
deals
INNER JOINcompanies
在companies
。id
=deals
。company_id
内部加入addresses
开启addresses
。addressable_id
=companies
。id
ANDaddresses
。addressable_type
='公司'WHEREdeals
。user_id
= 26 AND(地址范围37.483013038215276和38.06194017065867 AND addresses.lng BETWEEN -122.78956461309022 AND -122.05716204286986) 通过...分组 deals.id,deals.created_at,deals.updated_at,deals.user_id,deals.company_id, address.lat,addresses.lng拥有3958.755864232 * 2 * ASIN(SQRT(POWER(SIN)(37.772476604436974 - addresses.lat)* PI()/ 180 / 2),2)+ COS(37.772476604436974 * PI()/ 180)* COS(addresses.lat * PI()/ 180)* POWER(SIN(( - 122.42336332798004 - addresses.lng)* PI()/ 180/2),2)))&lt; = 20订购3958.755864232 * 2 * ASIN(SQRT(POWER(SIN)(37.772476604436974 - addresses.lat)* PI()/ 180 / 2),2)+ COS(37.772476604436974 * PI()/ 180)* COS(addresses.lat * PI()/ 180)* POWER(SIN(( - 122.42336332798004 - addresses.lng)* PI()/ 180/2),2)))ASC)AS t1 WHEREdeals
。user_id
= 26 GROUP BY id,created_at,updated_at,user_id,company_id ORDER BY distance ASC 限制1
我正在尝试用ARel做什么?上面的其他范围对我来说真的很脏(将子查询解析为原始SQL?我认为ARel应该这样做,所以我从来没有这样做过!)
相关问题:ARel能否为CTE(公用表格表达式)制定跨数据库查询?