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 „Gefällt mir“
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