2017-05-13 3 views
3

J'ai TempTable avec données:Comment utiliser DISTINCT ON (de PostgreSQL) dans Firebird?

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

Je veux obtenir les données suivantes:

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

Dans PostgreSQL, j'utilise une requête avec DISTINCT ON:

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

Firebird , comment obtenir des données comme ci-dessus les données?

Répondre

5

La clause DISTINCT ON de PostgreSQL prend la première ligne par clé de groupe déclarée compte tenu de la clause ORDER BY. Dans d'autres SGBD (y compris les versions ultérieures de Firebird), vous utiliseriez ROW_NUMBER pour cela. Vous numérotez les lignes par clé de groupe dans l'ordre souhaité et restez avec celles numérotées # 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; 

Dans votre exemple, vous avez un lien (key_1 = 2/= 0001 Clé_2 se produit deux fois) et le SGBD choisit une des lignes arbitrairement. (Vous devez étendre la clé de tri à la fois dans DISTINCT ON et ROW_NUMBER pour décider lequel choisir.) Si vous voulez deux lignes, c'est-à-dire afficher toutes les lignes liées, vous utiliserez (ou DENSE_RANK) au lieu de ROW_NUMBER, ce qui est quelque chose DISTINCT ON n'est pas capable de.

4

Firebird 3.0 prend en charge les fonctions de fenêtre, de sorte que vous pouvez utiliser:

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

Dans les versions précédentes, vous pouvez utiliser plusieurs méthodes. Voici une sous-requête corrélative:

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

Note: Ceci renvoie encore des valeurs en double pour key_1 en raison des doublons pour key_2. Hélas! . . obtenir une seule ligne est difficile, sauf si vous avez un identifiant unique pour chaque ligne.

+0

"sauf si vous avez un identifiant unique pour chaque ligne" ... et vous le faites. http://www.ibexpert.net/ibe/index.php?n=Doc.TheMysteryOfRDBDBKEY –