2016-02-15 8 views
9

私はRuby On RailsでPostgres PostGISを使ってこれをしようとしています。ruby​​ on railsの注文リストからcountサブクエリをグループ化する方法

私はグループ化を行い、私が持っている順序付きリストの都市を数えようとしています。

私は私の座標(110.1862202 1.6031959)に最も近い点の順序付けられたリストを持っています。

今、都市別にグループ化し、各都市のアイテム数を数えたいと思います。 しかし、書式は正しいものの、何らかの形で注文が失われています。私は都市が私の座標に最も近いように命令したいと思います。全体のポイントは、最も近い都市を取得することですが、現在では最も近い都市を取得することです。

=> {"Kuala Lumpur"=>1, "null"=>1, "Sungai Besar"=>1, "Sungai Udang"=>1, "Kuching"=>1} 

期待成果

=> {"Kuching"=>1, "Sungai Besar"=>1, "Sungai Udang"=>1, "Kuala Lumpur"=>1, "null"=>1} 

クエリの問題グループと

サブクエリ

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 
    } 
を数える実際の結果は、私の注文クエリが

正常に動作します(正しい)順序付けの
Treasure.order("ST_Distance(treasures.location_point, 
     ST_GeographyFromText('SRID=4326;POINT(110.1862202 1.6031959)'))") 

結果

=> #<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>]> 

注:私は副問合せを言われたんではないため、おそらく外が動作する可能性があり参加。そのようなクエリを作成するには?

答えて

3

実際には、ここでは注文が動作しないようになっているものがいくつかあります。あなたが言及したように

  • まず、サブクエリ内の任意ORDER句 - あなたの場所のクエリがであるものである - 最終的な結果セットの順序とは無関係であることを行っています。

  • 第2に、GROUP BY city句を使用すると、論理的に結果を明確に並べることができなくなります。都市X、距離= 10、都市Yの宝B、距離= 15、都市X、距離= 20の宝物Cを保有しているとします。 City Xはあなたの結果の最初または最後に来るでしょうか?

    しかし、すべての都市がほぼ同じ地域に宝を入れると仮定するのは妥当だと思うので、最も近い宝物で注文するのが妥当です。だから私たちはその問題を処理することができます。

  • 最後に、Railsのgroup().countは現在、値のハッシュをカウントに出力します。そのAPIはおそらくかなり新しく、変更される可能性があります(ハッシュは実際には注文しないでください、私の意見では、フォーマットはあまり拡張できません)。だからそれに頼ることは悪い考えかもしれません。しかし、私のテストから、が要求された順序で結果を吐き出します。要するに

、私たちがしなければならないことはあなたのクエリのトップレベル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 
} 
+0

を感謝ロバートNubelは、あなたを検証します技術。ところで、どこで最も近いアイテムの数を制限するために.limit()を置くことができますか(たとえばわずか30)。ありがとう。 – Axil

+0

'.count'がそれを行う前に(つまり' group(...)。order(...)。limit(30).count')。期待どおりに動作しないかどうか教えてください。 –

+0

こんにちは@ロベルトヌベル、限界が正しくありません。都市数(この例では30都市)に制限されています。私たちはカウントの数に制限することはできますか? – Axil

関連する問題