具有相同列值的 PostgreSQL select 行

PostgreSQL select rows having same column values

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

我想 select speed = 0lat && long 相同的所有位置

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

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

Note:: Speed is constant 0 but lat and long depend on previous rows value

您可以使用 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

我实际上将其视为 gaps-and-islands 问题,其中您希望相邻行具有相同的纬度和经度,并且速度为 0

您可以使用 window 函数解决此问题:行号之间的差异为您提供岛屿:然后您可以计算每个岛屿的长度,并过滤那些长度大于 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

还有一个解决方案:

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

上测试

如果你想要相邻的行,你可以只使用 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。一个是根据location id along计算的。第二个是基于纬度和经度的上一个或下一个。当这些相同时,相邻行的值相同。