Entwickler-Ecke

Datenbanken - Zeilenzähler in einer SQL-Abfrage


DelphiGreenhorn - Mi 05.09.07 13:31
Titel: Zeilenzähler in einer SQL-Abfrage
Hallo Forum,

bin grad etwas hilflos.
Gibt es eigentlich keine Ansi-SQL Lösung um eine Zählerspalte auszugeben?

Beispiel:

Select increment(1), lfdnr, adresse from adresstabelle
------------------------------------------------------
increment lfdnr adresse

1 4309 Hauptstraße 3
2 5890 Goethestraße 19
3 7890 Humboldtstraße 34
usw...


Jemand eine Idee?

MfG


noidic - Mi 05.09.07 13:35

in ANSI-SQL gibts das afaik nicht. Wozu braucht man auch Zeilennummern bei ner SQL-Abfrage?


DelphiGreenhorn - Mi 05.09.07 13:38

Keine Ahnung was der Vertrieb damit bezwecken will.

Muss jetzt dann aber dann aus dem einen Statement drei machen... für SQL-Server, Oracle und Informix.

Jemand zufällig die Info für die drei Server für mich?

MfG


ene - Mi 05.09.07 14:34

Hi,

Kannst du mit dem Beispiel ganz unten [http://www.jans-hp.de/?section=access&thema=sql&page=bsp] was anfangen? Solange SubSelects gehen, kann man damit arbeiten, ansonsten muss man sich eine Zählfunktion einbauen.


DelphiGreenhorn - Do 06.09.07 09:09

Kann leider nicht viel mit anfangen.

Müsste doch bestimmt irgendwelche TransactSQL/PL*SQL-Befehle geben, mit denen ich einfach in der Ausgabe eine fortlaufende Nummer erzeugen kann. Habe mich schon durch die Hilfe gewühlt, aber noch nix gefunden.

MfG


mkinzler - Do 06.09.07 09:19

Wenn du die SPs für jedes der DBMS schreibst könte es einfach gehen.


jasocul - Do 06.09.07 09:26

Es gibt Lösungen. Alle führen dazu, dass die Abfragen mehr oder weniger langsamer werden. Das solltest Du dem Vertrieb mal klar machen. Wenn es keinen wirklich zwingenden Grund für die Zeilennummern gibt, dann rate ich davon ab. Oft geht es nur darum, dass es so aussehen soll, wie in Excel.

Kläre also erstmal ab, wofür das benötigt wird. Eventuell wird es gar nicht benötigt oder es gibt bessere Lösungen. So auf Anhieb fällt mir jedenfalls nichts ein, wo man das wirklich benötigt.

EDIT:
Gib mal bei Google Suche bei Google ZEILENZ?HLER SQL als Suchbegriff ein.

Sehe gerade, dass der Vertrieb das für das MIS benötigt. Ich würde trotzdem mal nachfragen, wofür dort Zeilennummern benötigt werden. Als Vergleich zur Datenbankabfrage ist es nämlich unbrauchbar. Die nächste Abfrage kann schon wieder andere Ergbnisse liefern. Frage also lieber genau nach.


DelphiGreenhorn - Do 06.09.07 09:28

Ja, das wäre theoretisch die beste Möglichkeit.

Da der Vertrieb das für die Auswertung in unserem MIS-System benötigt und sonst nicht viel Ahnung von Datenbanken hat, wir auch nicht die Möglichkeit haben bei den Kunden die SPs zu platzieren sind mir da etwas die Hände gebunden.
Habe halt die Möglichkeit die Statements pro Datenbanktyp zu splitten und die Abfragen entsprechend anzupassen, oder eine allgemeingültige Lösung zu finden.

Ich habe eigentlich immer noch die Hoffnung mit datenbankspezifischen Abfragen an mein Ziel zu kommen. So eine Art ZeilenID für jede Ausgabespalte sollte sich doch machen lassen, oder?

MfG


DelphiGreenhorn - Do 06.09.07 09:33

Bin jetzt mal auf eine Lösung gekommen die funktionieren könnte.

Zitat:
select (select count(lfdnr) from adresse as X where X.lfdnr<= adresse.lfdnr) as NR , adresse.lfdnr from adresse where adressentyp = 'p' order by 1


Muss jetzt mal schauen, wie unsere DIN A4-Seiten großen Abfragen damit zurecht kommen.

Die Abfragen dürfen ruhig 10-15 Sek. brauchen, eine zeitkritische Verarbeitung ist nicht gegeben.

MfG


jasocul - Do 06.09.07 09:35

user profile iconDelphiGreenhorn hat folgendes geschrieben:
...und sonst nicht viel Ahnung von Datenbanken hat...
Es ist Deine Aufgabe (bzw. die des DB-Admin), hier für mehr Durchblick zu sorgen. Würde übrigens auch zeigen, dass Du mit denkst. Manche Geschäftsführung ist davon positiv überrascht.

user profile iconDelphiGreenhorn hat folgendes geschrieben:
Ich habe eigentlich immer noch die Hoffnung mit datenbankspezifischen Abfragen an mein Ziel zu kommen. So eine Art ZeilenID für jede Ausgabespalte sollte sich doch machen lassen, oder?
Eine ID sollte jeder Datensatz haben. Das ist natürlich keine ZeilenID.

user profile iconDelphiGreenhorn hat folgendes geschrieben:
Die Abfragen dürfen ruhig 10-15 Sek. brauchen, eine zeitkritische Verarbeitung ist nicht gegeben.
Reiche den Vertrieblern den kleinen Finger und sie fressen die ganze Hand. Weise auf die Probleme hin, damit es nicht irgendwann heißt, dass man doch überall die Zeilennummer einführen könnte.


DelphiGreenhorn - Do 06.09.07 09:41

Also der Vertrieb argumentiert mit einer besseren Auswertbarkeit der Abfrageergebnisse. Der Kunde hat diese Anforderung an uns herangetragen und die Geschäftsführung steht zu 100% hinter der Forderung des Kunden. Ist ja nicht so, als hätte ich das nicht schon alles versucht :)

MfG


mkinzler - Do 06.09.07 09:50

Die Frage ist nur, ob diese Nr in der SQL-Abfrage erzeugt werden muß oder es nicht besser wäre diese clientseitig zu erzeugen.


jasocul - Do 06.09.07 09:50

user profile iconDelphiGreenhorn hat folgendes geschrieben:
Also der Vertrieb argumentiert mit einer besseren Auswertbarkeit der Abfrageergebnisse.
:rofl: Das bezweifle ich sehr.

user profile iconDelphiGreenhorn hat folgendes geschrieben:
Der Kunde hat diese Anforderung an uns herangetragen und die Geschäftsführung steht zu 100% hinter der Forderung des Kunden.
Nicht jede Anforderung eines Kunden ist sinnvoll. Natürlich soll sich ein System dem User anpassen und nicht umgekehrt, aber manchmal sollten die User auch lernfähig sein. Ach egal, ich kenne genug User dieser Art. Warte mal ein Jahr ab. Dann meckert der Kunde, dass die Abfragen zu langsam sind.

user profile iconDelphiGreenhorn hat folgendes geschrieben:
Ist ja nicht so, als hätte ich das nicht schon alles versucht :)
Auch das kenne ich. Aber wer hat behauptet, dass wir ein leichtes Leben mit unserem Job haben. :wink:


DelphiGreenhorn - Do 06.09.07 10:00

user profile iconmkinzler hat folgendes geschrieben:
Die Frage ist nur, ob diese Nr in der SQL-Abfrage erzeugt werden muß oder es nicht besser wäre diese clientseitig zu erzeugen.


Dazu müsste man ja ein NCARS ändern ;) Das ist hier nicht gewünscht. Klingt komisch, ist aber so.
Manchmal muss man sich einfach den Entscheidungen fügen, besonders in dieser Firma :roll:

MfG


alzaimar - Do 06.09.07 10:56

Prinzipiell kann man Anfragen dieser Art relativ kostengünstig über eine Zwischentabelle lösen. Die Zwischentabelle enthält alle Felder der Abfrage und zusätzlich ein AutoInc-Feld (die Zeilennummer). Wie man ein AutoInc-Feld im jeweiligen DBMS implementiert, sollte bekannt sein.

Dann sieht das ungefähr so aus
1. Erzeuge eine temporäre Tabelle, die die Ergebnisse der Abfrage beinhalten
2. Füge eine AutoInc-Spalte zu dieser Tabelle hinzu (die ZeilenNr), das geht mit 'ALTER TABLE', schätze ich.
3. Liefere diese Tabelle ab und lösche sie dann wieder (u.U. unnötig, da temporär)


ene - Do 06.09.07 11:10

Einspruch euer Ehren. Zumindest der MS-SQL Server kennt temporäre Tabellen nur innerhalb einer SP. Danach sind sie nicht verfügbar! Auch weiß ich nicht ob alle DBMS ein SELECT ... INTO ... kennen. Wenn die Tabelle aber tatsächlich vorhanden ist und 3 Leute wollen darin unterschiedliche Daten sehen, muss man es noch um einen Benutzer erweitern. Das sind aus meiner Sicht aber alles Änderungen, die an der eigentlichen Datenbank und dann im Client gemacht werden müssen.


alzaimar - Do 06.09.07 11:31

user profile iconene hat folgendes geschrieben:
Einspruch euer Ehren. Zumindest der MS-SQL Server kennt temporäre Tabellen nur innerhalb einer SP. Danach sind sie nicht verfügbar!

Nicht innerhalb einer Session? (Steht so in der OH). Trotzdem klappts:
Ich baue mir eine SP mit einer lokalen temporären Tabelle, fülle die mit der Query, und liefere sie zurück.

SQL-Anweisung
1:
2:
3:
4:
Select * into #tmp from MyQuery
Alter Table #tmp Add ZeilenNr int Not Null IDENTITY (1, 1)
select * from #tmp
drop table #tmp

Blöd nur, man sieht
user profile iconSQL-Query Analyzer hat folgendes geschrieben:
(10 rows affected)
(10 rows affected)
(10 rows affected)

So gehts besser (ist aber nicht ganz so hübsch)

SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
set nocount on
Select * into #tmp from MyQuery
Alter Table #tmp Add ZeilenNr int Not Null IDENTITY (1, 1)
set nocount off
select * from #tmp
set nocount on
drop table #tmp 
set nocount off


Einen kleinen Nachteil hat die Methode: Die Zeilennummer ist die letzte Spalte der Tabelle. Wer das nicht will, muss sich die temporäre Tabelle explizit anhand der Strukturinformation der Abfrage erstellen. Unschön, aber möglich.

Dessenungeachtet sollte diese (verständliche) Vorgabe vom Kunden (a.k.a. Zeilennummern) vom Reportingtool zu erschlagen sein. Wenn es das nicht kann, dann sollte man es auf den Müll schmeissen.

Sch**** Vertrieb, wird nur getoppt vom Sch**** Marketing.


jasocul - Do 06.09.07 11:39

user profile iconalzaimar hat folgendes geschrieben:
Sch**** Vertrieb, wird nur getoppt vom Sch**** Marketing.
Mein Reden. Das Leben könnte so schön sein ohne User. :wink:

Aber zurück zum Thema.
Es bleibt immer noch das Problem, dass es für die verschiedenen DBMS gelöst werden soll. Oracle kennt z.B. kein AutoInc. Dort werden Sequences verwendet. Also muss für jedes DBMS eine separate Lösung gefunden werden. Ob das vom Manangement gewollt ist? (-> Kostenfrage, Pflegeaufwand, etc.)


Ramon - Do 06.09.07 11:42

Meine unter Oracle würde es auch so gehen:

SQL-Anweisung
1:
Select ROWNUM,lfdnr, adresse from adresstabelle                    


Ramon - Do 06.09.07 11:45

Für MS SQL mal hier schauen:
http://support.microsoft.com/default.aspx?scid=KB;EN-US;q186133


jasocul - Do 06.09.07 11:46

Und das mir als Oracle-Spezi :oops: :lol:


Amiga-Fan - Do 06.09.07 13:24

man könnte auch die Suchenfunktion benutezn :)

http://www.delphi-forum.de/viewtopic.php?t=57205&highlight=oracle+rownum