【问题标题】:PostgreSQL select rows having same column valuesPostgreSQL 选择具有相同列值的行
【发布时间】:2021-02-06 09:56:16
【问题描述】:
  | location_id  |  lat  |  long  |  speed  |
    ------------- ------- -------- --------- 
      101241        0.12    1.1       0.0    
    ------------- ------- -------- --------- 
      101242        0.12    1.1       0.0
    ------------- ------- -------- --------- 
      101243        0.12    1.1       0.0
    ------------- ------- -------- --------- 
      101244        1.25    0.74      7.4
    ------------- ------- -------- ---------

我想选择speed = 0 和lat && long 相同的所有位置

所以从上面的示例答案应该是::

   | location_id  |
    --------------
        101241     
    --------------
        101242     
    --------------
        101243     
    --------------

注意:速度是常数 0 但 lat 和 long 取决于之前的行值

【问题讨论】:

  • 到目前为止你尝试过什么?向我们展示一些努力。
  • 我尝试使用 PHP SQL 并且工作正常......但我有大量数据,所以我需要一些也能提供一些性能的东西
  • @Andronicus,如果你知道的话请告诉...我真的很感激
  • 不相关,但是:子选择中的order by完全没用

标签: sql postgresql window-functions gaps-and-islands


【解决方案1】:

我实际上将其理解为间隙和岛屿问题,您希望相邻行具有相同的纬度和经度,并且速度为0。

您可以使用窗口函数来解决此问题:行号之间的差异为您提供岛屿:然后您可以计算每个岛屿的长度,并过滤这些长度大于 1 并且其速度为 0 的:

select *
from (
    select t.*, count(*) over(partition by lat, long, speed, rn1 - rn2) cnt
    from (
        select t.*, 
            row_number() over(order by location_id) rn1,
            row_number() over(partition by lat, long, speed order by location_id) rn2
        from mytable t
    ) t
) t
where speed = 0 and cnt > 1

Demo on DB Fiddle

【讨论】:

    【解决方案2】:

    你可以使用inner join:

    select distinct t1.id
    from table_name t1
    inner join table_name t2
    on t1.location_id <> t2.location_id 
    and t1.lat = t2.lat
    and t1.long = t2.long
    where t1.speed = 0
    and t2.speed = 0
    

    或存在:

    select t.id
    from table_name t
    where exists (
        select *
        from table_name it
        where t.location_id <> it.location_id 
        and t.lat = it.lat
        and t.long = it.long
        and it.speed = 0
    )
    and t.speed = 0
    

    【讨论】:

    • 检查 #EDIT1 没有一个答案符合我的要求
    • 你会帮忙吗?
    【解决方案3】:

    另一种解决方案:

    SELECT location_id 
    FROM device_location 
    WHERE (lat, long) IN (
      SELECT lat, long
      FROM device_location
      WHERE speed = 0.0
      GROUP BY lat, long
      HAVING COUNT(*) > 1
    );
    

    在SQLize.online上测试它

    【讨论】:

      【解决方案4】:

      如果你想要相邻的行,你可以使用 lead() 和 lag() 。 . .但使用locationid 有一个小技巧:

      select t.*
      from (select t.*,
                   lag(locationid) over (order by locationid) as prev_locationid,
                   lead(locationid) over (order by locationid) as next_locationid,
                   lag(locationid) over (partition by lat, long order by locationid) as prev_locationid_ll,
                   lead(locationid) over (partition by lat, long order by locationid) as next_locationid_ll
            from t
           ) t
      where speed = 0 and
            (prev_locationid = prev_locationid_ll or
             next_locationid = next_locationid_ll
            );
      

      仅比较位置 ID。一个是根据位置 ID 计算得出的。第二个是基于经纬度的上一个或下一个。如果这些相同,则相邻行的值相同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-08
        • 2014-07-14
        • 1970-01-01
        • 1970-01-01
        • 2012-03-03
        • 2015-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多