none
Feldinhalt bei Werten von - bis ermitteln RRS feed

  • Allgemeine Diskussion

  • Hallo zusammen,

    ich habe ein Sachverhalt was mir gerade etwas Probleme macht. Vlt. hat der eine oder andere ein Tipp für mich.

    Ich muss aus einem Feld Daten lesen. Die Daten in der einen Spalte sind wie folgt hinterlegt:

    Feld: PLZ

    Datensatz1: 70100-75399

    Datensatz2: 75400-76999

    Datensatz3: 77000-89199, 90,92

    Ich soll als Beispiel bei der Suche der PLZ 70150 den Datensatz 1 finden. Bei der Suche 90 oder 77100 soll der Datensatz 3 gefunden werden.


    Dienstag, 14. März 2017 12:53

Alle Antworten

  • Hi,

    trenne die Werte in zwei Spalten (nspw. MinValue, MaxValue) oder (was ich für besser halten würde, da es teils ja auch mehr als zwei Werte geben kann) erstell dir eine separate Tabelle für die Werte.

    [PLZBereiche]
    ID
    ElterndatensatzId
    MinWert
    MaxWert
    

    In "ElterndatensatzId" kommt der Primärschlüsselwert des eigentlichen Datensatzes. In MinWert und MaxWert kommen dann bspw. 70100 und 75399, 77000 und 89199, 90 und 90, 92 und 92, usw.

    Dann kannst Du die Datensätze so ermitteln:

    SELECT ...
    FROM   Tabelle
    WHERE  ID IN (
                  SELECT ElterndatensatzId
                  FROM   PLZBereiche
                  WHERE  @Wert BETWEEN MinWert AND MaxWert
                 )
    


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Dienstag, 14. März 2017 13:16
    Moderator
  • Vielen Dank für die Antwort. Leider ist das der Weg den ich nicht gehen kann, da ich mit der Datenstruktur Wie oben beschrieben konfrontiert werde.
    Mittwoch, 15. März 2017 23:13
  • Hi,

    dann geht es nicht. Zumindest nicht per SQL. Man könnte natürlich auf sehr aufwändigem und zeitraubendem Weg versuchen, den Quatsch anderweitig zu parsen, über Hilfstabellen usw. zu arbeiten aber ehrlich gesagt macht das wenig bis keinen Sinn und falls da mehr als nur ein paar hundert Datensätze vorkommen, wird das auch nichts, was man der Abfrageperformance her haben will.

    Ich würde daher, wenn es gar nicht anders geht, eine bspw. nächtlich laufende Routine schreiben, die genau das oben gesagt macht, also die vorliegenden Daten parst und daraus eine Struktur baut, wie die, die ich oben gezeigt hatte. Diese Tabelle kann auch in einer anderen Datenbank liegen, wenn es sein muss.

    Und sag demjenigen, der diese "Struktur" (die keine ist) verbrochen und die Anforderung, sowas zu filtern, gestellt hat, dass er bitte die Finger von Datenbanken lassen soll.

    (Und Nein, das meine ich nicht böse, auch wenn es wahrscheinlich so klingt. Es bringt nur nichts, wenn jemand ohne Ahnung sowas kaputtes plant und dann Anforderungen stellt, die in dieser Struktur völlig abwegig sind).

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community




    Donnerstag, 16. März 2017 06:30
    Moderator
  • Hi Poli,
    bei solch nicht normalisierter Datenbankstruktur, empfiehlt es sich, eine StoreProcedure auf Basis einer SQL CLR dll zu erstellen und dann im Programm wie eine Stored Procedure zu nutzen.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Donnerstag, 16. März 2017 09:00
  • Hallo wie wäre es hiermit?

    create FUNCTION [dbo].[sf_chk_Bereich]
    (
        @Bereich            varchar (100),
        @Wert               int
    )
    returns bit
    as
    begin
        DECLARE
            @idx1       int,
            @Part       varchar (100),
            @idx2       int,
            @von        int,
            @bis        int;

        SET @idx1 = charindex (',', @Bereich);

        while (@idx1 > 0)
        BEGIN
            SET @idx1 = charindex (',', @Bereich);
            SET @Part = ltrim (rtrim (substring (@Bereich, 1, @idx1 - 1)));

            SET @idx2 = charindex ('-', @Part);

            if (@idx2 > 0)
            BEGIN
                set @von = convert (int, ltrim (rtrim (substring (@Part, 1, @idx2 -1))));
                set @bis = convert (int, ltrim (rtrim (substring (@Part, @idx2 + 1, 100))));
            END
            else
            BEGIN
                set @von = convert (int, ltrim (rtrim (@Part)));
                set @bis = @von;
            END

            if (@Wert between @von and @bis)
                return 1;

            SET @Bereich = ltrim (substring (@Bereich, @idx1 + 1, 100));
            SET @idx1 = charindex (',', @Bereich);
        END

        return 0;
    end
    GO

    SELECT PLZ from Tabelle where [dbo].[sf_chk_Bereich] (PLZ, @Wert) = 1;
     



    Donnerstag, 16. März 2017 16:55
  • Hallo Willi Spies,

    Erstmal vielen Dank für den Denkansatz, den Du mit der Skalarwertfunktion gegeben hast. Ich habe jedoch bemerkt, dass die Funktion 0 zurückgibt, wenn die Zeichenfolge nur aus einem Intervall besteht, wie z.B. '70100-75399' oder wenn man nach dem letzten Wert (nach dem letzten Komma) sucht, z.B.

    SELECT [dbo].[sf_chk_Bereich]('70100-75399,91,93',93)

    Deine Funktion kann angepasst werden, indem anfangs SET @idx = 1 hinzugefügt wird, damit auch bei einem Bereich wie '70100-75399' die Schleife durchlaufen wird. Darüber hinaus wird die Funktion nach dem Wert, der sich nach dem letzten Komma befindet, suchen, wenn folgende Zeile am Ende der while-Schleife entfernt wird (da Du den Wert am Anfang der Schleife zuweist):

    SET @idx1 = CHARINDEX(',',@Bereich);

    Zusammengefasst etwa:

        SET @idx = 1;
        while (@idx1 > 0)
          BEGIN
             SET @idx1 = charindex (',', @Bereich);
             IF idx1 > 0
                SET @Part = ltrim (rtrim (substring (@Bereich, 1, @idx1 - 1)));
             ELSE
                SET @Part = @Bereich                      --für den Fall eines Bereichs vom Typ '70100-70355'
             SET @idx2 = charindex ('-', @Part);
          
             --...
    
             SET @Bereich = ltrim (substring (@Bereich, @idx1 + 1, 100));
           END
    

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Montag, 20. März 2017 10:11
    Administrator