Return 给定特定列排序顺序的每一行的第一个条目 table

Return first entry in table for every row given a specifc column sort order

我有一个包含三列的 table,主机名、地址和虚拟。地址列是唯一的,但一台主机最多可以有两个地址条目,一个是虚拟的,一个是非虚​​拟的。换句话说,主机名和虚拟列对也是唯一的。我想生成一个结果集,其中包含一个主机的地址条目,优先考虑虚拟地址。例如,我有:

hostname | address | virtual
---------+---------+--------
first    | 1.1.1.1 | TRUE
first    | 1.1.1.2 | FALSE
second   | 1.1.2.1 | FALSE
third    | 1.1.3.1 | TRUE
fourth   | 1.1.4.2 | FALSE
fourth   | 1.1.4.1 | TRUE

查询应该return结果:

hostname | address 
---------+--------
first    | 1.1.1.1
second   | 1.1.2.1
third    | 1.1.3.1
fourth   | 1.1.4.1

这是每个主机的虚拟地址,以及缺少虚拟地址的主机的非虚拟地址。我最接近的是要求一位特定的主机:

SELECT hostname, address
FROM system
WHERE hostname = 'first'
ORDER BY virtual DESC NULLS LAST
LIMIT 1;

这给出了这个:

hostname | address 
---------+--------
first    | 1.1.1.1

如果可能的话,我想通过单个查询为 table 中的每个主机获取此信息。

在 Postgres 中,最简单的方法是 distinct on:

SELECT DISTINCT ON (hostname) hostname, address
FROM system
ORDER BY hostname, virtual DESC NULLS LAST

您要查找的是 RANK 函数。它看起来像这样:

SELECT * FROM (
    SELECT hostname, address
    , RANK() OVER (PARTITION BY hostname ORDER BY virtual DESC NULLS LAST) AS rk
    FROM system
)
WHERE rk = 1

这是一个可移植的解决方案,也适用于 Oracle 和 SQL 服务器。