【问题标题】:how to order and group by count subquery from an ordered list on ruby on rails如何从 ruby​​ on rails 的有序列表中按计数子查询排序和分组
【发布时间】:2016-05-26 04:42:42
【问题描述】:

我正在尝试使用 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
  }

实际结果

=> {"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}

我的订购查询工作正常

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

注意:有人告诉我子查询不排序,可能外连接可能有效。如何创建这样的查询?

【问题讨论】:

    标签: sql ruby-on-rails postgresql group-by


    【解决方案1】:

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

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

    • 其次,您的GROUP BY city 子句使您在逻辑上无法明确排序结果。假设你在X市有宝物A,距离=10,在Y市有宝物B,距离=15,在X市有宝物C,距离=20。 X 市会在您的结果中排在第一位还是最后一位?

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

    • 最后,Rails 的group().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
    }
    

    【讨论】:

    • 感谢 Robert Nubel,将验证您的技术。顺便说一句,我可以在哪里放置 .limit() 来限制最近项目的数量(例如只有 30 个)。谢谢。
    • .count 之前应该这样做(即group(...).order(...).limit(30).count)。让我知道它是否像您期望的那样工作。
    • 嗨@Robert Nubel,限制不正确。它仅限于数字城市(在本例中为 30 个城市)。我们可以限制计数的数量吗?
    • @Axil:我不关注。查询原样返回最近的 30 个城市。你在寻找什么?
    • 感谢您的回复。例如,如果 .limit(3),它会显示 3 个城市的计数。我打算拥有的“限制”是限制行/项目数的搜索查询结果。示例:cityA:10, cityB:15, cityC:5 ---> 因此总数为 30。所以假设我想将其限制为 30,这意味着查询计数结果的计数不应超过 30。你能理解这个吗 ?谢谢一百万!
    猜你喜欢
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多