我试图解决的问题是我有一个这样的表:
a和b指的是另一张桌子上的点。距离是点之间的距离。
| id | a_id | b_id | distance | delete |
| 1 | 1 | 1 | 1 | 0 |
| 2 | 1 | 2 | 0.2345 | 0 |
| 3 | 1 | 3 | 100 | 0 |
| 4 | 2 | 1 | 1343.2 | 0 |
| 5 | 2 | 2 | 0.45 | 0 |
| 6 | 2 | 3 | 110 | 0 |
....
我正在寻找的重要专栏是a_id。如果我想保留每个a的壁橱b,我可以这样做:
update mytable set delete = 1 from (select a_id, min(distance) as dist from table group by a_id) as x where a_gid = a_gid and distance > dist;
delete from mytable where delete = 1;
这会给我一个像这样的结果表:
| id | a_id | b_id | distance | delete |
| 1 | 1 | 1 | 1 | 0 |
| 5 | 2 | 2 | 0.45 | 0 |
....
即。对于a_id的每个值,我需要一行,并且该行应该具有每个a_id的最小距离值。
但是我想为每个a_gid保留10个最接近的点。我可以使用plpgsql函数执行此操作,但我很好奇是否有更多的SQL-y方式。
min()和max()返回最小和最大,如果有一个像nth()这样的聚合函数,它会返回第n个最大/最小值,那么我可以用与上面类似的方式做到这一点。 / p>
我正在使用PostgeSQL。
答案 0 :(得分:4)
我喜欢postgres,所以我在第二次看到这个问题时把它作为挑战。
所以,对于表:
Table "pg_temp_29.foo"
Column | Type | Modifiers
--------+---------+-----------
value | integer |
使用值:
SELECT value FROM foo ORDER BY value;
value
-------
0
1
2
3
4
5
6
7
8
9
14
20
32
(13 rows)
你可以做:
SELECT value FROM foo ORDER BY value DESC LIMIT 1 OFFSET X
其中X = 0表示最高值,1表示第二高,2 ......等等。
这可以进一步嵌入子查询中以检索所需的值。因此,要使用原始问题中提供的数据集,我们可以通过以下方式获得前十个最低距离的a_ids:
SELECT a_id, distance FROM mytable
WHERE id IN
(SELECT id FROM mytable WHERE t1.a_id = t2.a_id
ORDER BY distance LIMIT 10);
ORDER BY a_id, distance;
a_id | distance
------+----------
1 | 0.2345
1 | 1
1 | 100
2 | 0.45
2 | 110
2 | 1342.2
答案 1 :(得分:4)
试试这个:
SELECT *
FROM (
SELECT a_id, (
SELECT b_id
FROM mytable mib
WHERE mib.a_id = ma.a_id
ORDER BY
dist DESC
LIMIT 1 OFFSET s
) AS b_id
FROM (
SELECT DISTINCT a_id
FROM mytable mia
) ma, generate_series (1, 10) s
) ab
WHERE b_id IS NOT NULL
检查PostgreSQL 8.3
答案 2 :(得分:0)
PostgreSQL是否具有分析函数rank()?如果是这样,试试:
select a_id, b_id, distance
from
( select a_id, b_id, distance, rank() over (partition by a_id order by distance) rnk
from mytable
) where rnk <= 10;
答案 3 :(得分:0)
这个SQL应该找到你应该在SQL Server,MySQL,DB2,Oracle,Teradata和几乎任何其他RDBMS中工作的第N个最低工资:(注意:由于子查询而性能低下)
SELECT * /*This is the outer query part */
FROM mytable tbl1
WHERE (N-1) = ( /* Subquery starts here */
SELECT COUNT(DISTINCT(tbl2.distance))
FROM mytable tbl2
WHERE tbl2.distance < tbl1.distance)
在上面的查询中要理解的最重要的事情是,每次外部查询处理行时,都会对子查询进行求值。换句话说,内部查询不能独立于外部查询进行处理,因为内部查询也使用tbl1值。
为了找到第N个最低值,我们只找到恰好N-1值低于其自身的值。