INFORMIX / rownum

Hallo,
weiss jemand, ob es unter INFORMIX (XPS) etwas analoges zu Oracles ‚ROWNUM‘ gibt? Also eine Pseudospalte, die jede Row meines Abfrageergebnisses mitzaehlt (keine SERIALs, ROWID o.ae., also nichts, was als zusaetzlich Column in der Tabelle gespeichert werden muss).

Danke fuer Antworten.
Gruss
bernhard

Hallo Bernhard,

schau mal hier:

http://vyaskn.tripod.com/review_swissql_sqlone_conso…

Gruß

Peter

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Peter,

danke für den Hinweis, ich dachte schon, daß sich hier relativ wenige Leute mit Informix befassen (müssen).

Leider ist auf der Seite nicht die Lösung, die ich brauche.

Oracle:

SELECT \*
FROM
(
SELECT \*
FROM Employees 
ORDER BY EmployeeID DESC 
)
WHERE ROWNUM 
wird "übersetzt" nach Informix:


    
    SELECT FIRST 1 \*
    FROM
    (
    SELECT \*
    FROM Employees
    ORDER BY EmployeeID DESC
    ) AdventNet\_ALIAS1



Das ist ja auch richtig so - beide Abfragen haben dieselbe Funktionalität. Ich brauche aber die echte Rownum als Zahlenwert (mit dem ich später weiterarbeiten kann) und nicht nur die erste (oder ersten n) Zeile(n). 

Hintergrund: ich habe in einer Tabelle eine id (ggf. mehrfach) mit unterschiedlichen laufenden Nummern pro id (Spalte lfd\_nr, lfd\_nr ist nicht lückenlos aufsteigend gefüllt - also z.B. 2,3,5,17 ...). Die Tupel (id, lfd\_nr) sind jedoch eindeutig. Als Ergebnismenge brauche ich neue Tupel (id, neue\_lfd\_nr), wobei nur die maximal 6 (oder allg. n) kleinsten Werte von lfd\_nr zur selben id genommen werden sollen, ausserdem sollen die Werte der Spalte neue\_lfd\_nr von 1 bis max. 6 sortiert sein (also: min(lfd\_nr) -\> neue\_lfd\_nr =1, zweitkleinste -\> 2). Das ganze ist natürlich noch ein bischen komplizierter, da noch weitere Spalten bei der Aktion mitberücksichtigt werden. Eine Lösung mit Cursor (d.h. satzweise durchiterieren) scheidet aus Performancegründen aus (einige Mio. Records).

Bsp:


    
    id lfd\_nr -\> id neue\_lfd\_nr
    3 2 3 1
    3 4 3 2
    4 1 4 1
    4 7 4 2
    5 3 5 1
    5 6 5 2
    5 17 5 3
    5 22 5 4
    5 37 5 5
    5 38 5 6
    5 49 (kein Ergenissatz, da nur die 6 kleinsten Werte)
    6 -5 6 1
    6 0 6 2
    7 1 7 1
    7 3 7 2
    7 8 7 3




In dem Zusammenhand dachte ich an Oracle, Subselects und eben auch ROWNUM. Hat jemand eine brauchbare Idee?

danke & gruss
bernhard

Hallo Bernhard,

ich sehe eigentlich keine Lösung außer einer Prozedur:
Du brauchst zwei temporäre Variable temp_id = -999 und temp_lfdnr 0 -999 (jedenfalls außerhalb des Bereichsder ID)
Dann machst du einen select mit ORDER BY id, lfdnr
Bei jedem Datensatz vergleichst Du die Werte mit den temp_Werten, bei jedem Wechsel der Id wird die lfdnr wieder zurückgesetzt.
Bei Werten für id > 6 wird der Datensatz gelöscht (wenn das deine Absicht war)
Ansonsten schreibst du ihn in eine temporäre Tabelle und liest die nachher aus.
Ich glaube nicht, dass die die Zeilennummer etwas helfen würde. Die gibt dir nämlich die Zeile in der Tabelle und nicht eine fortlaufende Nummer der Ausgabe. So etwas könntest Du evtl mit einer Funktion erreichen:
Globale Variable definieren (zaehler)
Funktion schreiben, die zähler zurückgibt und inkrementiert.
Damit würde es dann vielleicht auch mit einem Select gehen.

Gruß

Peter

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

1 Like

Hallo Peter (und andere die evtl. mitlesen),

ich habe das ganze jetzt etwas umstaendlicher aber einigermaßen performant über zwei Zwischentabellen gelöst.
In etwa so:

insert into tmp\_table
select
 id, lfd\_nr
from ursprungs\_tabelle;

-- Block 

insert into tmp\_table2
select 
 id
 ,min(lfd\_nr) -- column: lfd\_nr
 ,1 -- neue\_lfd\_nr
 -- im folgenden mit Werten 2,..6 wiederholen
from tmp\_table
group by 1, 2, 4;

delete from tmp\_table
where exists(
 select 
 id, lfd\_nr 
 from 
 tmp\_table2
 where 
 tmp\_table2.id = tmp\_table.id
 and tmp\_table2.lfd\_nr = tmp\_table.lfd\_nr
);

-- die letzten 2 Statements (insert / delete) mit Werten 2,3,4,5,6
-- fuer den Insert wiederholen

...

-- und jetzt 
select 
 insert into tmp\_table
select
 ursprungs\_tabelle.id, 
 ,tmp\_table2.neue\_lfd\_nr
 ,ursprungs\_tabelle.
from 
 ursprungs\_tabelle u
 ,tmp\_table2 t
where
 t.id = u.id
 and t.lfd\_nr = u.lfd\_nr;

Vielleicht nicht die schönste Lösung, aber hat im Vergleich zu vorher
(Cursor-Verarbietung unter COBOL) einen mächtigen Performanceschub gebracht…

Vielleicht hat ja noch jemand Verbesserungsideen.

gruss
bernhard