如何从轨道上的ruby上的有序列表中的count子查询进行排序和分组

Axi*_*xil 9 sql postgresql group-by ruby-on-rails

我正在尝试使用Postgres PostGIS在Ruby On Rails上执行此操作.

我正在尝试进行分组并依靠我所拥有的有序列表中的城市.

我有一个最近点到我坐标的有序列表(110.1862202 1.6031959).

现在我想按城市分组并计算每个城市的项目数量.但是,格式是正确的,但不知何故它已经失去了它的排序.我希望这些城市的排序最接近我的坐标.最重要的是要到最近的城市,但现在它没有排序最近.

查询问题组和计数子查询

  scope :nearestcitysubquery, -> () {
    from(Treasure.order("ST_Distance(treasures.location_point, 
         ST_GeographyFromText('SRID=4326;POINT(110.1862202 1.6031959)'))"),
         "subquery_treasure_nearest").group("city").count
  }
Run Code Online (Sandbox Code Playgroud)

实际结果

=> {"Kuala Lumpur"=>1, "null"=>1, "Sungai Besar"=>1, "Sungai Udang"=>1, "Kuching"=>1}
Run Code Online (Sandbox Code Playgroud)

预期结果

=> {"Kuching"=>1, "Sungai Besar"=>1, "Sungai Udang"=>1, "Kuala Lumpur"=>1, "null"=>1}
Run Code Online (Sandbox Code Playgroud)

我的订购查询工作正常

Treasure.order("ST_Distance(treasures.location_point, 
         ST_GeographyFromText('SRID=4326;POINT(110.1862202 1.6031959)'))")
Run Code Online (Sandbox Code Playgroud)

订购结果(这是正确的)

=> #<ActiveRecord::Relation [#<Treasure id: 5, user_id: 1, treasure_name: "Kucing", treasure_image: nil, description: "Kucing", hint: nil, location: "Jalan Ke Puncak Serapi", created_at: "2016-01-08 03:46:40", updated_at: "2016-01-08 03:46:40", treasure_id: "TRKKY", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942b71c8 "POINT (110.18 1.6)">, city: "Kuching", state: "Sarawak", country: "Malaysia", difficulty: 2, google_place_id: "ChIJZf_iRaYF-zERMH5qt30cJJw", size: 2>, #<Treasure id: 4, user_id: 1, treasure_name: "Lori", treasure_image: nil, description: "Lori", hint: nil, location: "Jalan Samsudin", created_at: "2016-01-08 03:45:26", updated_at: "2016-01-08 03:45:26", treasure_id: "T3UKD", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942bbd68 "POINT (102.14 2.27)">, city: "Sungai Udang", state: "Melaka", country: "Malaysia", difficulty: 2, google_place_id: "ChIJq6_zCZX50TERBdlr6V1CMDg", size: 2>, #<Treasure id: 3, user_id: 1, treasure_name: "Kapal", treasure_image: nil, description: "Kapal", hint: nil, location: "Unnamed Road", created_at: "2016-01-07 09:21:07", updated_at: "2016-01-07 09:21:07", treasure_id: "T3XQR", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942ba29c "POINT (101.76 3.5)">, city: "null", state: "Selangor", country: "Malaysia", difficulty: 2, google_place_id: "ChIJWU_xuCoTzDERsigXByaXof4", size: 3>, #<Treasure id: 1, user_id: 1, treasure_name: "Kelapa", treasure_image: nil, description: "Food", hint: nil, location: "Jalan Kiara 3", created_at: "2016-01-07 06:08:56", updated_at: "2016-01-07 06:08:56", treasure_id: "TJKQL", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9943647d8 "POINT (101.65 3.17)">, city: "Kuala Lumpur", state: "Wilayah Persekutuan Kuala Lumpur", country: "Malaysia", difficulty: 2, google_place_id: "ChIJ8fBgm-1IzDERPHAF2dYtWTc", size: 2>, #<Treasure id: 2, user_id: 1, treasure_name: "Pulau", treasure_image: nil, description: "Pulau", hint: nil, location: "Jalan Parit 4 Barat", created_at: "2016-01-07 09:20:47", updated_at: "2016-01-07 09:20:47", treasure_id: "TO1BR", location_point: #<RGeo::Geographic::SphericalPointImpl:0x3fe9942bd744 "POINT (101.0 3.7)">, city: "Sungai Besar", state: "Selangor", country: "Malaysia", difficulty: 2, google_place_id: "ChIJAfwEx2lgyzERU_zVy8TqaW0", size: 3>]>
Run Code Online (Sandbox Code Playgroud)

注意:我被告知子查询没有命令,可能外连接可能有效.如何创建这样的查询?

Rob*_*bel 3

实际上,这里发生了一些事情,导致您的订单无法正常工作。

  • 首先,就像您提到的,ORDER子查询中的任何子句(即您的位置查询所在的子句)都与最终结果集的顺序无关。

  • 其次,你的GROUP BY city子句在逻辑上使得你不可能明确地对你的结果进行排序。假设你在X城市有宝藏A,距离=10,在Y城市有宝藏B,距离=15,在X城市有宝藏C,距离=20。X 城市在您的结果中会排在第一位还是最后一位?

    然而,我认为假设所有城市都在大致相似的区域包含宝藏是合理的,因此按最近的宝藏排序是合理的。所以我们可以处理这个问题。

  • 最后,Railsgroup().count目前输出一个值的哈希值来进行计数。该 API 可能相当新,并且可能会发生变化(在我看来,哈希值确实不应该被排序,而且格式的可扩展性不是很好)。所以依赖它可能是一个坏主意。但是,根据我的测试,它确实按请求的顺序输出结果。

简而言之,我们需要做的是将 移动order到查询的顶层。为此,order 子句需要使用聚合函数(我将选择 MIN,按最近的宝藏进行排序),我们可以删除花哨的代码.from

# I'm assuming this is on the Treasure model
scope :nearestcitysubquery, -> () {
  group('city')
    .order("MIN(ST_Distance(treasures.location_point, 
       ST_GeographyFromText('SRID=4326;POINT(110.1862202 1.6031959)')))")
    .count
}
Run Code Online (Sandbox Code Playgroud)