none
Datenmenge und Sortierungen RRS feed

  • Frage

  • Moin Leute,

    ich stelle von meiner alten Datenspeichertechnik um auf SQL-Server und bin da noch nicht richtig zu Hause. Nun hab ich ein Problem und bin mir nicht sicher ob das überhaupt so geht und ob ich die richtige SQL-Denke hab. Auf jeden Fall braucht mein User eine adäquate Lösung.

    Da passiert einfach folgendes: DBF-Datei,  der User gibt eine Arbeitsnummer (AN, char) ein , diese wird via Index AN gefunden und dann setze ich einen anderen (vorhandenen) Index namens Ordnung (=Feld1+Feld2+AN) und der User kann dann ausgehend von dem gefundenen Satz in diesem Bereich blättern.
    Wie kriege ich denn sowas in SQL hin? Also eine Teilmenge aus einer Tabelle fischen, Zeiger steht auf einem gesuchten Satz (eben dem mit der gesuchten (AN) und "davor" und "dahinter" stehen 20, 30,40 Sätze nach einer anderen Ordnung ?
    Geht das überhaupt so? performant muss das natürlich auch noch sein.

    Grüsse von der Weser

    Horst

    Mittwoch, 13. Juni 2012 07:22

Alle Antworten

  • Gehen ja, aber es hängt von den von dir eingesetzten Techniken ein. Womit entwickelst du (Sprache, Entwicklungsoberfläche, bisher eingesetzte Datenzugriffskomponenten und Controls)?
    Mittwoch, 13. Juni 2012 09:04
    Moderator
  • Hallo Stefan,

    Sprache ist VFP9. SQL-Select -Befehle sind integriert. Ich brauche also im Prinzip nur einen passenden Select...-Befehl (stelle ich mir jedenfalls vor).
    Reicht Dir diese Info ?

    Mittwoch, 13. Juni 2012 09:24
  • Ouch, mit VFP habe ich noch nix gemacht. Eventuell reicht ein einfaches Upsizing..
    Mittwoch, 13. Juni 2012 11:29
    Moderator
  • nun ja, dann wirst Du damit auch nie etwas tun.( Auslaufmodell leider )

    Aber mal ganz davon abgesehen: Ich vereinfache mein Problem mal. Ganz einfach gefragt: ich suche einen Satz mit :
    select * from tabelle where AN = Usereingabe.
    und ich weiß das damit nur ein Satz gefunden wird (AN gibt es jeweils nur einmal).(oder keiner)

    Gibt es dann eine Möglichkeit durch eine Erweiterung des Select-Befehls diesen Satz und 20 weitere zu holen die einem 'order by AN' entsprächen?

    Ich hab so das dumme Gefühl das geht garnicht und auch das es irgendwie verdammt kompliziert ist wenn die Tabelle selber keinen Index kennt.
    Irgendwie ist mir die Philosophie wohl noch zu fremd.
    Dabei ist die Problemstellung eigentlich simpel: der User möchte durch Teile seiner Daten nach einer bestimmten Ordnung durchblättern.
    Aber eben nur durch Teile und wo er beginnen muss bestimmt er durch die Eingabe.

    Vielleicht hast Du (oder irgendwer?) ja trotzdem einen allgemeinen Tipp (oder einen Literaturhinweis: Datensalat für Dummmies oder so)

    Mittwoch, 13. Juni 2012 12:44
  • Hallo Horst,

    seit der Version 2005 gibt es die sogenannten Window Functions. Aktuell gibt es auch noch ein Buch dazu, das erste Kapitel ist auch kostenlos:
    http://www.insidesql.org/blogs/cmu/sql_server/high-performance-tsql-window-functions

    Du könntest über ROW_Number() einen Paging Mechanismus implementieren, oder ab 2012 mit OFFSET/FETCH arbeiten.
    Das hier habe ich auf die schnelle gefunden:
    http://beyondrelational.com/modules/2/blogs/28/posts/10434/sql-server-server-side-paging-with-rownumber-function.aspx
     Einen schönen Tag noch,
    Christoph
    --
    Microsoft SQL Server MVP
    www.insidesql.org/blogs/cmu

    Mittwoch, 13. Juni 2012 12:51
  • Ich danke Dir Christoph,

    das sieht alles sehr interessant aus und ich werd mich gleich mal intensiver damit beschäftigen. Ich denke aber das ich diese Infos auf jeden Fall gebrauchen kann da ich nicht nur eine Umsetzung habe sondern zukünftig sowieso viel mit dem SQL(-Server) zu tun habe.( Und dann auch mit C#).

    Dir auch noch einen schönen Tag :-))

    Horst

    Mittwoch, 13. Juni 2012 13:10
  • Hallo Horst,

    ich arbeite auch mit VFP und nutze den SQL-Server seit fast zehn Jahren. Ich bin bisher noch auf kein Problem gestossen, welches mit dem SQL-Server nicht vergleichbar zu lösem wäre. Das meiste geht wesentlich eleganter.

    Indizes brauchst Du auf dem SQL-Server nur zur Beschleunigung der Zugriffe, nicht zur Sortierung der Abzeige.

    Wie selektierst Du denn jetzt?

     Wenn Du ein Filterkriterium über mehrere Felder brauchsr kannst Du z.B. eine View benutzen.

    CREATE VIEW myView AS SELECT *,Feld1+feld2+AN AS ordnung FROM ...

    Dein SQL-Statement müsste dann so aussehen

    SELECT TOP 20 * FROM myView WHERE ordnung ...

    Das ist alles ist aber sehr theoretisch, gib doch einmal ein Beispiel. Bei der Eingabe einer AN sollen welche DS angezeigt werden?

    Gruss Uli


    • Bearbeitet Uli Münch Donnerstag, 14. Juni 2012 06:14
    Donnerstag, 14. Juni 2012 06:13
  • Hallo Ulli,

    sorry, wenn ich jetzt erst antworte. Ich hatte direkt nach dem Posting einen Noteinsatz, ein intensives Familien-WE und Montags musste ich zum Kunden. Wo die Zeit so bleibt ist einfach grauenhaft. Nun werd ich mich wieder mit diesem Problem beschäftigen. Dein erster Absatz macht mir richtig Mut. Insgesamt hab ich ja doch ein wenig Sorgen wie das mit der Performance alles so aussehen wird. Ganz nebenbei: ich arbeite ja mit VFX und CA und will dann die Lösung auch irgendwie da mit einbauen. Aber das dürfte kein grosses Problem sein hoffe ich. Fritz hat mir auch schon eine Lösung gepostet. Ich beschreib aber mein Problem trotzdem nochmal, vielleicht hast Du ja noch eine Bemerkung, Verbesserung, Ablehnung oder anderen Kommentar dazu. Ich muss und ich will auf jeden Fall dazulernen weil ich in Zukunft nur noch auf dem SQL-Server speichere und die nativen Tabellen nur noch in Ausnahmefällen zulässig sind.

    Also: Die Daten kommen auf verschiedenen Wegen in die Tabelle. Der User kennt nur die AN die eindeutig! ist. In diesem eindeutigen Satz befinden sich die Felder Feld1 und Feld2 die das nicht sind und die der User nicht kennt und deren Gruppe die eigentliche Datenumgebung ist wo der User hinwill. In Fox mache ich das ganz einfach:

    set order to AN
    seek UsereingabeAN
    set order to Ordnung (=Feld1+Feld2+AN)

    und fertig. Nun kann er in seiner gewünschten Datenumgebung rauf und runter blättern.

    Die Lösung ist wohl: mit der Eingabe den einen Satz via
    "select ..where Usereingabe = AN into cursor Zwi"    in einen Zwischencursor holen,  via
     "select.. where Feld1 = zwi.Feld1 AND Feld2 = zwi.Feld2 "  dann die endgültigen Daten holen. Hört sich jetzt so einfach an, aber mit meiner Fox-Denke (s.o.)  wars erstmal kompliziert. Und wie wird die Perfomance sein ? ich werd mal rangehen ...... oder weißt Du was besseres ?

    Auf jeden Fall Danke für deine Antwort und  schönes WE

    Horst

    Freitag, 22. Juni 2012 08:02
  • Hallo Horst,

    mir fehlt immer noch ein wenig die Logik dieses Vorgehens. Du solltest Dir evtl. einmal die LIKE-Klausel anschauen, hier kannst Du Platzhalter u.ä. verwenden.

    http://msdn.microsoft.com/de-de/library/ms179859.aspx

    Denkbar wäre auch

    SELECT * FROM mytable WHERE feld1 IN (SELECT feld1 FROM mytable WHERE an = < Usereingabe>)

    oder so

    SELECT * FROM mytable WHERE feld1+feld2 IN (SELECT feld1+feld2 FROM mytable WHERE an = < Usereingabe>)

    Probier es doch einfach einmal aus.

    Gruss Uli

    Dienstag, 26. Juni 2012 11:13
  • Hallo Ulli

    Danke Dir wirklich für Deine Mühe. Das Problem löse ich inzwischen mit einem Zwischencursor und bei mir sieht die Performance auch ganz gut aus.

    >>SELECT * FROM mytable WHERE feld1+feld2 IN (SELECT feld1+feld2 FROM mytable WHERE an = < Usereingabe>)

    Dieser Vorschlag ist auch gangbar, vielleicht baue ich (je nach performance beim Kunden auch noch mal um).

    Mir ist allerdings aufgefallen das ich auch zuviel in den Datenstrukturen des Kunden denke mittlerweile (die ich ganz gut kenne).  Wenn alles etwas anders gelagert wäre würde das so nicht funktionieren.Aber des Lerneffektes halber würde mich jetzt noch folgendes interessieren (aber beschäftgie Dich bitte nur damit wenn Du auch die Zeit hast! das Problem für die Kundendaten ist erstmal gelöst, keine Zeitbombe mehr für mich, ich will nicht aus lauter Jux und Tollerei anderen Arbeit beschaffen :-)))

    Also:

      Satz     An    Feld1   Feld2

       1         1      Otto     Hamburg

       2         2      Otto     Hamburg

       3         3      Otto    Dortmund

       4         4      Karl      Berlin

       5         5      Karl      München

       6         6      Emil     Dortmund

    Angenommen der User kennt nur die An = 3. Wäre es dann trotzdem möglich diese Sätze (geordnet nach Feld1+Feld2+An) mit einem Select -Befehl zu erhalten? In Fox würde fogendes passieren: Satzzeiger landet bei Satz 3. Index auf Feld1+Feld2+An gesetzt, sähe die Sache so aus:

      Satz     An    Feld1   Feld2

       6         6      Emil     Dortmund

       4         4      Karl      Berlin

       5         5      Karl      München

       3         3      Otto    Dortmund

       1         1      Otto     Hamburg

       2         2      Otto     Hamburg

    Wie Du siehst passt der Karl garnicht ins Bild (weder Otto noch Dortmund), ich will aber alle Sätze beim Durchblättern so haben.Und halt noch 10 "drunter" und "drüber" . Machbar???

    Grüsse von der Weser

    Horst

    Mittwoch, 27. Juni 2012 07:49
  • Hallo Horst,

    machbar ist alles. Wenn Du die View_ordnung aus dem folgenden Code auf Deiner DB anlegst, sollte das Ergebnis des  letzten Statements ziemlich  Deinem Anliegen entsprechen.

    Ich würde allerdings diese Statement in eine Proc oder Func packen um diese Abrage nur einmal ausführen zu müssen

    (SELECT ranking FROM view_ordnung where an = @usereingabe)

    Gruss Uli




    IF NOT EXISTS ( SELECT * FROM sys.tables
        JOIN sys.schemas  ON sys.tables.schema_id = sys.schemas.schema_id
       WHERE sys.tables.name = N'test' )
    BEGIN
    CREATE TABLE test
      (an int,feld1 varchar(30) ,feld2 varchar(30) )


    insert into test (an,feld1,feld2)VALUES(1,'Otto','Hamburg')
    insert into test (an,feld1,feld2)VALUES(2,'Otto','Hamburg')
    insert into test (an,feld1,feld2)VALUES(3,'Otto','Dortmund')
    insert into test (an,feld1,feld2)VALUES(4,'Karl','Berlin')
    insert into test (an,feld1,feld2)VALUES(5,'Karl','München')
    insert into test (an,feld1,feld2)VALUES(6,'Emil','Dortmund')

    END
    GO

    /*
    IF object_id(N'dbo.view_ordnung', 'V') IS NOT NULL
        DROP VIEW dbo.view_ordnung
    */


    create view dbo.view_ordnung as select rank()OVER (ORDER BY a.feld1, a.feld2) as ranking, * from test a
    GO

    DECLARE @usereingabe int
    set @usereingabe= 3

    select an,feld1,feld2 from view_ordnung where ranking between (SELECT ranking FROM view_ordnung where an = @usereingabe)-10
     and  (SELECT ranking FROM view_ordnung where an = @usereingabe)+10




    DROP VIEW dbo.view_ordnung
    DROP TABLE test




    • Bearbeitet Uli Münch Donnerstag, 28. Juni 2012 08:06
    Donnerstag, 28. Juni 2012 08:03