Formatieren von Rekord-dates-String mit einer function

Hallo ich habe eine kleine function, die ich nicht verstecken kann Ich würde das generell in der Anwendungsschicht machen, aber habe nicht die Möglichkeit damit und mein T-SQL ist ein wenig rostig.

Vereinfachte function: (Nehmen Sie ein date und berechnen Sie wiederholte Termine im Intervall)

CREATE FUNCTION [dbo].[fn_GetRunDatesShort] (@startDate DateTime, @weeks INTEGER) RETURNS VARCHAR(1000) AS BEGIN DECLARE @i INTEGER DECLARE @interval INTEGER DECLARE @outPut VARCHAR(500) SET @outPut = '' SET @i = 0 SET @interval = 7 WHILE (@i < @weeks) BEGIN SET @output = @outPut + ', ' + Convert(varchar, DATEPART(MONTH, DATEADD(d, @interval, @startDate)),101) + '-' + Convert(varchar, DATEPART(d, DATEADD(d, @interval, @startDate))) SET @interval = @interval + 7 SET @i = @i + 1 END RETURN @output END GO SELECT dbo.fn_GetRunDatesShort(GETDATE(), 4) 

So kommt das zurück

 , 8-21, 8-28, 9-4, 9-11 

Ich muss das zurückkehren

 August 21, 28 | September 4, 11 

Versuchen Sie, loops zu vermeiden, wenn Sie Sets viel effizienter erzeugen können , und bitte aufhören, varchar ohne Länge zu erklären .

Hier ist eine function, die alle Ihre Anforderungen kombiniert (generieren Sie den Satz von data und formatieren sie in Ihrem ungünstigen Ausgabeformat):

 CREATE FUNCTION dbo.fn_GetRunDatesShort_2 ( @StartDate DATE, @Weeks TINYINT ) RETURNS VARCHAR(MAX) AS BEGIN DECLARE @output VARCHAR(MAX); ;WITH cte1(m,d) AS ( SELECT DATENAME(MONTH, wd), CONVERT(VARCHAR(2), DAY(wd)) FROM ( SELECT TOP (@Weeks) DATEADD(WEEK, ROW_NUMBER() OVER (ORDER BY [object_id]), @StartDate) FROM sys.all_objects ORDER BY [object_id] ) AS sq(wd) ), cte2(ds) AS ( SELECT DISTINCT m + STUFF((SELECT ', ' + d FROM cte1 AS cte1_a WHERE cte1_a.m = cte1.m FOR XML PATH(''), TYPE).value('.[1]','varchar(max)'),1,1,'') FROM cte1 ) SELECT @output = STUFF((SELECT ' | ' + ds FROM cte2 FOR XML PATH(''),TYPE).value('.[1]','varchar(max)'),1,3,''); RETURN (@output); END GO 

(Wenn du eine Numbers-Tabelle hast – was du solltest – kannst du die Abfrage gegen sys.all_objects an eine ähnliche gegen die Numbers-Tabelle replace und dann kannst du WITH SCHEMABINDING zur function hinzufügen – was in diesem Fall nicht helfen kann, aber Es ist etwas , was ich versuche, konsequent zu machen, wann immer möglich .)

Verwendung:

 SELECT dbo.fn_GetRunDatesShort_2(GETDATE(), 4); 

Ergebnisse:

 August 21, 28 | September 4, 11 

Das Problem kommt, wenn Ihr @weeks 52 @weeks – welche Ausgabe erwarten Sie, wenn Sie data vom August dieses Jahres haben und aus dem August des nächsten Jahres stammen?


EDIT 2014-05-19

Um die Bestellung in der richtigen Richtung zu gewährleisten (etwas, das im letzten August gut gelaufen ist, aber im Mai die Reihenfolge zu ändern scheint), kannst du diese Änderung an der function vornehmen:

 CREATE FUNCTION dbo.fn_GetRunDatesShort_2 ( @StartDate DATE, @Weeks TINYINT ) RETURNS VARCHAR(MAX) AS BEGIN DECLARE @output VARCHAR(MAX); ;WITH cte1(mn,m,d) AS ( SELECT DATEPART(YEAR, wd) * 100 + DATEPART(MONTH, wd), DATENAME(MONTH, wd), CONVERT(VARCHAR(2), DATEPART(DAY,wd)) FROM ( SELECT TOP (@Weeks) DATEADD(WEEK, ROW_NUMBER() OVER (ORDER BY [object_id]), @StartDate) FROM sys.all_objects ORDER BY [object_id] ) AS sq(wd) ), cte2(mn,ds) AS ( SELECT DISTINCT mn, m + STUFF((SELECT ', ' + d FROM cte1 AS cte1_a WHERE cte1_a.m = cte1.m ORDER BY mn FOR XML PATH(''), TYPE).value('.[1]','varchar(max)'),1,1,'') FROM cte1 ) SELECT @output = STUFF((SELECT ' | ' + ds FROM cte2 ORDER BY mn FOR XML PATH(''),TYPE).value('.[1]','varchar(max)'),1,3,''); RETURN (@output); END GO 

Um zu vermeiden, durch die FOR XML-Engine zu gehen, darf ich eine Fall-Statement-Struktur vorschlagen?

 CREATE FUNCTION dbo.fn_GetRunDatesShort_2 ( @StartDate DATE, @Weeks TINYINT ) RETURNS VARCHAR(MAX) AS BEGIN DECLARE @output VARCHAR(MAX) SET @output = '' SELECT @output = @output + CASE @output WHEN '' THEN M ELSE CASE R WHEN 1 THEN ' | ' + M ELSE '' END END + ' ' + CASE R WHEN 1 THEN '' ELSE ', ' END + D FROM ( SELECT year(DT) as Y, datename(month,DT) as M, CAST(datepart(day,DT) AS VARCHAR) AS D , row_number()over(partition by month(DT), year(dt) order by day(DT)) AS R , row_number()over(order by dt) AS R2 FROM ( SELECT dateadd(ww,row_number()over(order by object_id), @StartDate) AS DT FROM master.sys.objects ) z ) y WHERE R2 <= @weeks ORDER BY R2 RETURN @output END GO 

Ausgabe von SELECT dbo.fn_GetRunDatesShort_2(GETDATE(),5)

 May 26 | June 2 , 9 , 16 , 23 

Dies könnte auch bearbeitet werden, wenn das Jahr des dates wichtig für die Ausgabe ist.