none
String Spliten und dann daraus Anzahl bestimmte Datums herausgeben RRS feed

  • Frage

  • Hallo,

    ich habe in der Spalte feiertage in der Tabelle dbo.feiertag einen String, der bestimmte Einträge mit Komma getrennt beinhaltet. In den Einträgen sind auch Datums dabei.

    Jetzt möchte ich gerne die Anzahl von Datums von einem bestimmten Jahr haben rausgeben.

    Kann jemand mir vielleicht sagen, ob und wie ich das machen könnte?


    Gruesse, NUNUI

    Montag, 26. Dezember 2016 13:40

Antworten

  • Hi,

    Du solltest nicht mit kommaseparierten Werten in einer Spalte arbeiten, wenn Du die einzelnen Werte noch verarbeiten musst. Ändere dein Datenbankdesign lieber so, dass die Werte in einer separaten Tabelle stehen.

    Da ich aber ehrlich gesagt nicht rauslesen kann, wie in deinem Fall was wo gespeichert ist, poste bitte das CREATE TABLE Statement für deine Tabelle, INSERT INTO Statements für die Beispieldaten und das gewünschte Ergebnis deiner Abfrage, basierend auf diesen Beispieldaten.


    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

    Montag, 26. Dezember 2016 14:11
    Moderator
  • Hallo,

    dass das Tabellendesign so nicht sinnvoll ist, haben ja die anderen schon geschrieben.

    Wenn Du SQL Server 2016 verwendest, kannst Du die STRING_SPLIT (Transact-SQL) Funktion zum Splitten und die TRY_CONVERT (Transact-SQL) Funktion zum sicheren Konvertieren verwenden.

    Beispiel:

    DECLARE @data varchar(8000) = 
    'Niedersachsen;01.01.2016;Neujahr;NJ;25.03.2016;Karfreitag;KF;28.03.2016;Ostermontag;OM;01.05.2016;Tag der Arbeit;TA;05.05.2016;Christi Himmelfahrt;CH;16.05.2016;Pfingstmontag;PM;03.10.2016;Tag der Deutschen Einheit;DA;25.12.2016;1. Weihnachtstag;1W;26.12.2016;2. Weihnachtstag;2W;01.01.2017;Neujahr;NJ;14.04.2017;Karfreitag;KF;17.04.2017;Ostermontag;OM;01.05.2017;Tag der Arbeit;TA;25.05.2017;Christi Himmelfahrt;CH;05.06.2017;Pfingstmontag;PM;03.10.2017;Tag der Deutschen Einheit;DA;31.10.2017;Reformationstag;RT;25.12.2017;1. Weihnachtstag;1W;26.12.2017;2. Weihnachtstag;2W';
    
    ;WITH cte AS
        (SELECT SUB.value, TRY_CONVERT(datetime, SUB.value) AS Datum
    	 FROM STRING_SPLIT(@data, ';') AS SUB
    	 WHERE ISDATE(SUB.value) = 1)
    
    SELECT *, DATENAME(weekday, cte.Datum)
    FROM cte
    WHERE YEAR(cte.Datum) = 2016
          AND DATENAME(weekday, cte.Datum) <> 'Sonntag'
    Eine gute Performanz darf man hier aber nicht erwarten.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]


    Dienstag, 27. Dezember 2016 17:59

Alle Antworten

  • Hi,

    Du solltest nicht mit kommaseparierten Werten in einer Spalte arbeiten, wenn Du die einzelnen Werte noch verarbeiten musst. Ändere dein Datenbankdesign lieber so, dass die Werte in einer separaten Tabelle stehen.

    Da ich aber ehrlich gesagt nicht rauslesen kann, wie in deinem Fall was wo gespeichert ist, poste bitte das CREATE TABLE Statement für deine Tabelle, INSERT INTO Statements für die Beispieldaten und das gewünschte Ergebnis deiner Abfrage, basierend auf diesen Beispieldaten.


    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

    Montag, 26. Dezember 2016 14:11
    Moderator
  • Hallo Stefan,

    Die Tabelle wird wie folgt erzeugt:

    CREATE TABLE [dbo].[feiertage](
    	[id] [int] IDENTITY(1,1) NOT NULL,
    	[feiertage] [text] NULL,
     CONSTRAINT [PK_feiertage] PRIMARY KEY CLUSTERED 
    (
    	[id] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    Und der Text, was in der Spalte feiertage eingetragen ist (pro Bundesland):

    Niedersachsen;01.01.2016;Neujahr;NJ;25.03.2016;Karfreitag;KF;28.03.2016;Ostermontag;OM;01.05.2016;Tag der Arbeit;TA;05.05.2016;Christi Himmelfahrt;CH;16.05.2016;Pfingstmontag;PM;03.10.2016;Tag der Deutschen Einheit;DA;25.12.2016;1. Weihnachtstag;1W;26.12.2016;2. Weihnachtstag;2W;01.01.2017;Neujahr;NJ;14.04.2017;Karfreitag;KF;17.04.2017;Ostermontag;OM;01.05.2017;Tag der Arbeit;TA;25.05.2017;Christi Himmelfahrt;CH;05.06.2017;Pfingstmontag;PM;03.10.2017;Tag der Deutschen Einheit;DA;31.10.2017;Reformationstag;RT;25.12.2017;1. Weihnachtstag;1W;26.12.2017;2. Weihnachtstag;2W

    Und jetzt möchte ich Anzahl der Tage, die keine Sonntag sind, z.B. für das Jahr 2016 herausgeben.

    Hoffe, könnte ich es einigermaßen verständlich erklären!


    Gruesse, NUNUI

    Montag, 26. Dezember 2016 14:49
  • Hallo Nunui,

    wie Stefan bereits geschrieben hat ist dein Tabellendesign eher ungeeignet dafür. Hier würde es sich anbieten drei Spalten zu nutzen

    Datum (date)

    Bundesland char(30)

    Feiertagname char(20)

    mit einem Primärschüssel über die Spalten Datum und Bundesland. Zudem wäre eine Dimensionstabelle mit Datumswerten hilfreich um die Vergleiche zu beschleunigen. 


    Benjamin Hoch
    MCSE: Data Platform
    MCSE: Data Management and Analytics
    MCSA: SQL Server 2012/2014
    MCSA: Windows Server 2012
    Blog

    Montag, 26. Dezember 2016 16:55
  • Hallo,

    dass das Tabellendesign so nicht sinnvoll ist, haben ja die anderen schon geschrieben.

    Wenn Du SQL Server 2016 verwendest, kannst Du die STRING_SPLIT (Transact-SQL) Funktion zum Splitten und die TRY_CONVERT (Transact-SQL) Funktion zum sicheren Konvertieren verwenden.

    Beispiel:

    DECLARE @data varchar(8000) = 
    'Niedersachsen;01.01.2016;Neujahr;NJ;25.03.2016;Karfreitag;KF;28.03.2016;Ostermontag;OM;01.05.2016;Tag der Arbeit;TA;05.05.2016;Christi Himmelfahrt;CH;16.05.2016;Pfingstmontag;PM;03.10.2016;Tag der Deutschen Einheit;DA;25.12.2016;1. Weihnachtstag;1W;26.12.2016;2. Weihnachtstag;2W;01.01.2017;Neujahr;NJ;14.04.2017;Karfreitag;KF;17.04.2017;Ostermontag;OM;01.05.2017;Tag der Arbeit;TA;25.05.2017;Christi Himmelfahrt;CH;05.06.2017;Pfingstmontag;PM;03.10.2017;Tag der Deutschen Einheit;DA;31.10.2017;Reformationstag;RT;25.12.2017;1. Weihnachtstag;1W;26.12.2017;2. Weihnachtstag;2W';
    
    ;WITH cte AS
        (SELECT SUB.value, TRY_CONVERT(datetime, SUB.value) AS Datum
    	 FROM STRING_SPLIT(@data, ';') AS SUB
    	 WHERE ISDATE(SUB.value) = 1)
    
    SELECT *, DATENAME(weekday, cte.Datum)
    FROM cte
    WHERE YEAR(cte.Datum) = 2016
          AND DATENAME(weekday, cte.Datum) <> 'Sonntag'
    Eine gute Performanz darf man hier aber nicht erwarten.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]


    Dienstag, 27. Dezember 2016 17:59
  • Es wird SQL SERVER 2012 eingesetzt. Und bekomme leider folgende Fehlermeldung:

    'TRY_CONVERT' wird nicht als Name einer integrierten Funktion erkannt.


    Gruesse, NUNUI

    Dienstag, 27. Dezember 2016 18:11
  • TRY_CONVERT gibt es ab SQL Server 2012, wenn Du trotzdem eine Fehlermeldung erhält, dann weil die Datenbank in einem älteren Kompatibilitätsmodus läuft; siehe Anzeigen oder Ändern des Kompatibilitätsgrads einer Datenbank

    STRING_SPLIT gibt es erst ab 2016, deswegen mein Hinweis, kannst Du aber durch dieses Skript ersetzen: Convert Small CSV Value to Table


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Dienstag, 27. Dezember 2016 18:31
  • Danke, bekomme aber jetzt folgende Fehlermeldung :o)

    Ungültiger Objektname 'STRING_SPLIT'.

    Es ist wahrscheinlich sinnvoller, den Tabellendesign zu ändern! Das Problem ist, dass ich auch dann an vielen Stellen im Programm den Code ändern muss. Lässt sich leider doch nicht vermeiden!


    Gruesse, NUNUI



    • Bearbeitet Nunui Dienstag, 27. Dezember 2016 19:11
    Dienstag, 27. Dezember 2016 19:09
  • Hi,

    die sinnvollste Variante ist sicherlich die Änderung des Datenbankdesigns. Und achte zukünftig darauf, dass Du nicht mehrere Werte als String zusammenfasst, wenn Du die einzelnen Elemente noch in irgendeiner Form weiterverarbeiten musst (zumindest, wenn Du das per SQL machen musst)

    Zur Fehlermeldung an sich: Olaf schrieb doch, dass STRING_SPLIT erst ab SQL Server 2016 zur Verfügung steht. Da du SQL Server 2012 verwendest, kann also nichts anderes als eine Fehlermeldung kommen.


    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, 27. Dezember 2016 21:50
    Moderator
  • Aber möchte mich für die Unterstützung sehr bedanken :o)

    Gruesse, NUNUI

    Dienstag, 27. Dezember 2016 21:52