具有相同列值的 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 = 0
和 lat
&& 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
还有一个解决方案:
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
);
上测试
如果你想要相邻的行,你可以只使用 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计算的。第二个是基于纬度和经度的上一个或下一个。当这些相同时,相邻行的值相同。
| 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 = 0
和 lat
&& 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
还有一个解决方案:
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
);
上测试
如果你想要相邻的行,你可以只使用 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计算的。第二个是基于纬度和经度的上一个或下一个。当这些相同时,相邻行的值相同。