none
Ermitteln eines Folgedatensatzes innerhalb einer Sortierung abhängig von Kriterien RRS feed

  • Frage

  • Hallo zusammen,

    ich habe folgende Tabelle eines Werkskalenders für verschiedene Werke:

    CREATE TABLE [dbo].[Werkskalender](
    	[Werk-ID] [nvarchar](4) NOT NULL,
    	[Datum] [varchar](10) NOT NULL,
    	[Arbeitstag-Flag] [char](1) NOT NULL
    ) ON [PRIMARY]
    GO
    SET ANSI_PADDING ON
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130101', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130102', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130103', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130104', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130105', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130106', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130107', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130108', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130109', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130110', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130111', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130112', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130113', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130114', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130115', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130116', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130117', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130118', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130119', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130120', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130121', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130122', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130123', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130124', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130125', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130126', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130127', N'0')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130128', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130129', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130130', N'1')
    GO
    INSERT [dbo].[Werkskalender] ([Werk-ID], [Datum], [Arbeitstag-Flag]) VALUES (N'1001', N'20130131', N'1')
    GO

    Ziel ist es nun, für jeden Datensatz den jeweils nächsten Arbeitstag (Arbeitstag-Flag = 1) zu ermitteln, falls im aktuellen Datensatz Arbeitstag-Flag = 0 ist. Man müsste also so lange zum nächsten Datensatz springen, bis dieser nicht mehr Flag=0 hat und dann das Datum dieses Datensatzes im ursprünglichen Datensatz vermerken.

    Die Zieltabelle hätte demnach folgendes Format.

    Werk-ID, Datum, Arbeitstag-Flag, Datum_Arbeitstag_Korrektur

    1, 20130101, 0, 20130102

    1, 20130102, 1, 20130102

    1, 20130103, 1, 20130103

    1, 20130104, 1, 20130104

    1, 20130105, 0, 20130107

    1, 20130106, 0, 20130107

    1, 20130107, 1, 20130107

    Vermutlich kann man etwas mit Window-Fuktionen machen, mir fehlt aber eine Idee, wie ich dieses dynamische Fenster definieren kann... Kann jemand helfen?

    Viele Grüße

    Axel


    • Bearbeitet Axel Bergmann Donnerstag, 17. Oktober 2013 10:18 Codeblock ergänzt
    Donnerstag, 17. Oktober 2013 09:29

Antworten

  • Hallo Axel,

    das bei Dir "Datum" ein varchar(10) ist, ist hier nicht so optimal, besser wäre ein Integer oder Date Typ. Dann kannst Du es mit einem einfachen Subselect lösen:

    SELECT *
          ,(SELECT TOP 1 SUB.[Datum]
            FROM [dbo].[Werkskalender] AS SUB
            WHERE SUB.[Arbeitstag-Flag] = 1
                  AND SUB.Datum > WK.Datum
            ORDER BY SUB.Datum ASC) AS NextWorkingDay
    FROM [dbo].[Werkskalender] AS WK

    Also: Ermittle den nächsten echt größeren Datumswert mit Arbeitstag-Flag = 1, davon aber nur den ersten nach aufsteigender Sortierung. Noch einen passenden Index dazu und dann sollte es gut laufen.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    • Als Antwort markiert Axel Bergmann Donnerstag, 17. Oktober 2013 11:40
    Donnerstag, 17. Oktober 2013 10:58

Alle Antworten

  • Hallo Axel,

    das bei Dir "Datum" ein varchar(10) ist, ist hier nicht so optimal, besser wäre ein Integer oder Date Typ. Dann kannst Du es mit einem einfachen Subselect lösen:

    SELECT *
          ,(SELECT TOP 1 SUB.[Datum]
            FROM [dbo].[Werkskalender] AS SUB
            WHERE SUB.[Arbeitstag-Flag] = 1
                  AND SUB.Datum > WK.Datum
            ORDER BY SUB.Datum ASC) AS NextWorkingDay
    FROM [dbo].[Werkskalender] AS WK

    Also: Ermittle den nächsten echt größeren Datumswert mit Arbeitstag-Flag = 1, davon aber nur den ersten nach aufsteigender Sortierung. Noch einen passenden Index dazu und dann sollte es gut laufen.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    • Als Antwort markiert Axel Bergmann Donnerstag, 17. Oktober 2013 11:40
    Donnerstag, 17. Oktober 2013 10:58
  • Danke Olaf, funktioniert perfekt!


    Viele Grüße A. Bergmann

    Donnerstag, 17. Oktober 2013 11:42