6

我有一个带有数据的 TempTable:

------------------------------------
| KEY_1 | KEY 2 | NAME   | VALUE   |
------------------------------------
|     1 |  0001 | NAME 2 | VALUE 1 |
|     1 |  0002 | NAME 1 | VALUE 3 |
|     1 |  0003 | NAME 3 | VALUE 2 |
|     2 |  0001 | NAME 1 | VALUE 2 |
|     2 |  0001 | NAME 2 | VALUE 1 |
------------------------------------

我想得到以下数据:

------------------------------------
| KEY_1 | KEY 2 | NAME   | VALUE   |
------------------------------------
|     1 |  0001 | NAME 2 | VALUE 1 |
|     2 |  0001 | NAME 1 | VALUE 2 |
------------------------------------

在 PostgreSQL 中,我使用以下查询DISTINCT ON

SELECT DISTINCT ON (KEY_1) KEY_1, KEY_2, NAME, VALUE
FROM TempTable
ORDER BY KEY_1, KEY_2

在 Firebird 中,如何获取上述数据?

4

2 回答 2

7

Firebird 3.0 支持窗口函数,所以你可以使用:

select . . .
from (select t.*,
             row_number() over (partition by key_1 order by key_2) as seqnum
      from temptable t
     ) t
where seqnum = 1;

在早期版本中,您可以使用多种方法。这是一个相关的子查询:

select t.*
from temptable t
where t.key_2 = (select max(t2.key_2)
                 from temptable t2
                 where t2.key_1 = t.key_1
                );

注意:这仍然会返回重复的值,key_1因为key_2. 唉。. . 除非您对每一行都有唯一的标识符,否则只获取一行是很棘手的。

于 2017-05-13T18:58:49.037 回答
7

考虑到该子句,PostgreSQLDISTINCT ON采用每个声明的组键的第一行。ORDER BY在其他 DBMS(包括 Firebird 的更高版本)中,您会使用ROW_NUMBER它。您按所需顺序对每个组键的行进行编号,并保留编号为 #1 的行。

select key_1, key_2, name, value
from
(
  select key_1, key_2, name, value,
    row_number() over (partition by key_1 order by key_2) as rn
  from temptable
) numbered
where rn = 1
order by key_1, key_2;

在您的示例中,您有一个平局(key_1 = 2 / key_2 = 0001 出现两次)并且 DBMS 任意选择其中一行。(您必须同时扩展排序键DISTINCT ONROW_NUMBER决定选择哪一个。)如果您想要两行,即显示所有绑定的行,您将使用RANK(or DENSE_RANK) 而不是ROW_NUMBER,这DISTINCT ON是无法做到的。

于 2017-05-13T18:59:46.293 回答