2016-09-09 13 views
0

Ich möchte das Schuljahr jedes Mal erhöhen, nachdem das vorherige Schuljahr vorbei ist. Zum Beispiel sieht meine aktuellen Code wie folgt aus:Wie füge ich Neujahr hinzu?

WHERE schooldt BETWEEN '07/01/2016' AND '06/30/2017' 

So einmal Schuljahr ist vorbei 06/30/2017 Ich möchte neue Startdatum setzen und neue Enddatum automatisch. Ich habe darüber nachgedacht, dateAdd() in der kalten Fusion zu verwenden. Gibt es einen anderen Weg dies zu tun und was wäre am effizientesten?

Vielen Dank im Voraus.

+0

Woher wissen Sie, wann die Schule nächstes Jahr beginnt? Beginnt es immer am 1. Juli und endet am 30. Juni? – Alex

+0

Ja beginnt immer am 07/01 und endet am 30.06. Also möchte ich mein Startjahr erhöhen und mein letztes Jahr nach dem Schuljahr endet. –

+0

Der Rest der Abfrage ist relevant. Bitte posten Sie es. –

Antwort

6

Ich möchte Schuljahr nach Jahr vor der Schule jedes Mal erhöhen, ist über

Dann Logik implementieren, die die Datumswerte in der Abfrage ändert sich basierend auf den aktuellen Monat. Wenn der aktuelle Monat vor Juli liegt, wissen Sie, dass das laufende Schuljahr noch nicht abgeschlossen ist. Ziehen Sie daher ein Jahr ab, um das Startdatum zu berechnen. Andernfalls wechseln Sie zum nächsten Jahr.

<cfset today = now()> 
    <!--- If the current school year is still in progress ---> 
    <cfif month(today) lt 7> 
     <cfset startDate = createDate(year(today) - 1, 7, 1)> 
     <cfset endDate = createDate(year(today), 6, 30)> 
    <!--- Otherwise, move to next year ---> 
    <cfelse> 
     <cfset startDate = createDate(year(today), 7, 1)> 
     <cfset endDate = createDate(year(today) + 1, 6, 30)> 
    </cfif> 

Soweit Abfrage-, zwei Dinge im Auge zu behalten:

  • Datum Strings sind nicht eindeutig. Verwenden Sie stattdessen immer Datumsobjekte.
  • Seien Sie vorsichtig mit Datumsvergleichen und dem Operator BETWEEN. Wenn die Spalte SchoolDt sowohl ein Datum als auch eine Uhrzeit enthielt, entspricht das Ergebnis möglicherweise nicht Ihren Erwartungen. Ein flexibleres Konstrukt (das Stills funktioniert auch, wenn eine Spalte sowohl Datum und Uhrzeit enthält) ist:

    WHERE SchoolDt >= <cfqueryparam value="#startDate#" cfsqltype="cf_sql_date"> 
    AND SchoolDt < <cfqueryparam value="#dateAdd('d', 1, endDate)#" cfsqltype="cf_sql_date"> 
    

    Wenn Sie new Query() verwenden, parametrieren die SQL-Zeichenfolge und verwenden addParam statt:

    yourQuery.addParam(name="startDate" 
            , value="#startDate#" 
            , cfsqltype="cf_sql_date"); 
    
    yourQuery.addParam(name="endDate" 
            , value="#endDate#" 
            , cfsqltype="cf_sql_date"); 
    
+0

Danke! Das funktioniert ausgezeichnet, ich habe dateFormat() um create date verwendet. Ich bin mir nicht sicher, ob das die obige Logik ändern kann. –

+2

@espresso_coffee - Nein, verwende dateFormat() nicht, da es die date * objects * in Strings konvertiert (die mehrdeutig sind). DateFormat dient nur zur Präsentation, dh wenn Sie benutzerfreundliche Werte für Benutzer anzeigen müssen. Wenn Sie mit Datenbanken arbeiten (oder Datumsfunktionen verwenden), belassen Sie die Werte als Datumsobjekte. – Leigh

+0

Danke nochmal. Wenn ich dies verwende, um meine Abfrage auszuführen Muss ich cfqueryparam innerhalb von ArrayAppend() verwenden? –

2

Für die Datumstabelle Antwort:

CREATE TABLE calendar ( 
    SeqNum int 
    , schooldt date NOT NULL PRIMARY KEY 
    , theYear int 
    , theMonth tinyint 
    , theDay tinyint 
    , schoolyear int 
    , isSchoolDay tinyint /* Can count schooldays */ 
    , isHoliday tinyint /* Can count holidays. */ 
) 

DECLARE @StartDate date = '1/1/2010' 

/* Build tally table with 10^x rows */ 
; WITH TallyTable (x) AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
    FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(x)  -- 10 days 
    CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(x) -- 100 days 
    CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(x) -- 1000 days 
    CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(x) -- 10000 days 
) 
INSERT INTO calendar (SeqNum, schooldt, theYear, theMonth, theDay, schoolyear, isSchoolDay, isHoliday) 
SELECT 
    tt.x AS SeqNum 
    , d1.theDate 
    , d2.theYear 
    , d2.theMonth 
    , d2.theDay 
    , d2.theSchoolYear 
    , 1 , 0 /* Defaults for isSchoolDay and isHoliday. Add if needed. */ 
FROM TallyTable tt 
CROSS APPLY (
    SELECT theDate = DATEADD(dd, (tt.x-1), @StartDate) /* Starting date */ 
) d1 
CROSS APPLY 
( 
    SELECT theYear = DATEPART(yy,d1.theDate) 
     , theMonth = DATEPART(mm,d1.theDate) 
     , theDay = DATEPART(dd,d1.theDate) 
     , theSchoolYear = CASE WHEN DATEPART(mm,d1.theDate) < 7 THEN DATEPART(yyyy,d1.theDate) ELSE DATEPART(yyyy,d1.theDate)+1 END 
) d2; 

etwas in diesen lin Es wird Ihnen eine Liste von Tagen für mehrere Jahre geben. Dann können Sie sich diesem Tisch anschließen, um den gewünschten Bereich zu erhalten.

Um die Tabelle zu verbessern, können Sie Informationen zur Bezeichnung von Feiertagen und Wochenenden hinzufügen, sodass nur die Tage angezeigt werden, an denen die Schule tatsächlich stattfindet. Und am wichtigsten ist, dass Sie alles nach dem aktuellen Schuljahr filtern können, das Sie sehen möchten. Sie müssen sich keine Sorgen machen, das Schuljahr zu erhöhen, wenn es Zeit für einen Wechsel ist.

Aber es stellt sich wieder die Frage, was ist Ihr ultimatives Ziel dieser Abfrage? Möglicherweise gibt es sogar noch bessere Möglichkeiten, um Ihr Ziel zu erreichen.

Verwandte Themen