2011-09-07 17 views
13

In SQL Server 2008 l'isoweek può essere trovato con questo:Isoweek in SQL Server 2005

SELECT datepart(iso_week, getdate()) 

Prima di SQL Server 2008 non c'erano funzione built-in per trovare isoweek.

Ho cercato una sintassi buona e alta per trovare un iso_week definito dall'utente per SQL Server 2005. Ho trovato alcune soluzioni. Non mi è piaciuta nessuna delle soluzioni che ho trovato, la maggior parte di loro non ha funzionato, ed erano troppo lunghi.

Poiché il problema è molto vecchio, mi aspetto che questo problema sia esaurito e che sia stata trovata la soluzione migliore. Non sono riuscito a trovare un buon metodo però.

Ho scritto una soluzione, che pubblicherò dopo. Ma prima di farlo, voglio essere assolutamente sicuro che nessun altro possa eguagliare la soluzione che ho scritto.

Spero di guadagnare il distintivo del discente. Esorto le persone a trovare le migliori risposte là fuori per questa antica domanda.

Ho intenzione di pubblicare la mia risposta dopo aver dato alla gente la possibilità di trovare una buona soluzione.

+0

Insieme al numero della settimana è importante includere l'anno della settimana ISO, perché può differire dal normale anno. Questo sembra non banale. –

+0

@MicheldeRuiter link a iso_year [qui] (http://stackoverflow.com/questions/22829604/what-is-iso-year-in-sql-server/22830524#22830524) –

+0

Ho già trovato la tua risposta lì, buona per rendere gli altri lettori consapevoli. –

risposta

12

Ecco un approccio simile al tuo in quanto si basa anche sul giovedì di questa settimana. Ma alla fine usa la data in modo diverso.

  1. Ottenere la data di questo giovedì (ISO) della settimana.

    La propria soluzione utilizza la data codificata di un giovedì noto. In alternativa, di questa settimana Giovedi potrebbe essere trovata con l'aiuto di @@DATEFIRST:

    SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date) 
    

    (. Io non faticato troppo per la formula giusta perché era already known per me)

  2. Prendi il giorno del Giovedi dell'anno:

    SELECT DY = DATEPART(DAYOFYEAR, Th) 
    
  3. utilizzano il numero per scoprire settimana in questo modo:

    SELECT ISOWeek = (DY - 1)/7 + 1 
    

Qui ci sono i calcoli di cui sopra in un unico prospetto:

SELECT ISOWeek = (DATEPART(DAYOFYEAR, Th) - 1)/7 + 1 
FROM (
    SELECT Th = DATEADD(DAY, 3 - (DATEPART(WEEKDAY, @date) + @@DATEFIRST - 2) % 7, @date) 
) s; 
+0

+1 awsome, mi ci è voluto un po 'per capire cosa stavi facendo, finora ho deciso che stai imbrogliando, perché non ci ho pensato. Ho combinato le nostre risposte a una soluzione compatta molto breve. –

+0

Ti meriti davvero credito per questa soluzione, buon compagno di lavoro. –

+0

Grazie mille! –

34

C'è un link qui per altri tentativi precedenti http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=60510

Questo è il vecchio codice per la funzione

CREATE function f_isoweek(@date datetime) 
RETURNS INT 
as 
BEGIN 
DECLARE @rv int 

SELECT @rv = datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4) 
FROM (SELECT dateadd(ww, datediff(day, 0, @date)/7, 3) day4) a 

RETURN @rv 
END 

Dopo combinando risposta brillante @AndriyM 's con la mia, siamo scesi a 1 linea. Questo è il NUOVO codice.

CREATE function f_isoweek(@date datetime) 
RETURNS INT 
as 
BEGIN 

RETURN (datepart(DY, datediff(d, 0, @date)/7 * 7 + 3)+6)/7 
-- replaced code for yet another improvement. 
--RETURN (datepart(DY, dateadd(ww, datediff(d, 0, @date)/7, 3))+6)/7 

END 

Spiegazione per il vecchio codice (non andare a spiegare il nuovo codice E 'frammenti di mio codice e il codice di AndriyM.):

Trovare giorno della settimana 4 della data scelta

dateadd(week, datediff(day, 0, @date)/7, 3) 

Ricerca di isaia - l'anno del giorno della settimana 4 di una settimana è sempre lo stesso anno della settimana

datediff(yy, 0, day4) 

Quando si aggiungono 3 giorni per il primo giorno del isoyear un giorno a caso della prima isoweek del isoyear è trovato

dateadd(yy, datediff(yy, 0, day4),3) 

trovando settimana relativo della prima isoweek del isoyear

datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7 

Trovare il lunedi meno 4 giorni dei primi risultati isoweek a giovedi della settimana prima del primo giorno del primo isoweek del isoyear

dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4) 

Conoscendo primo giovedi di t la settimana prima della prima isoweek e il primo giovedì della settimana prescelta, , è abbastanza facile calcolare la settimana, non importa quale data di impostazione ha da quando i giorni feriali di entrambe le date sono giovedì.

datediff(ww, dateadd(ww, datediff(d, 0, dateadd(yy, datediff(yy, 0, day4),3))/7,-4),day4) 
+0

+1. Rispetto a questa versione http://msdn.microsoft.com/en-us/library/ms186755.aspx, la tua è una moltitudine migliore perché non dipende da 'set datefirst 1'. –

+0

Bello! E mi piace il tuo '(n + 6)/7' meglio del mio' (n - 1)/7 + 1'. Avrei svalutato di nuovo, se potessi. –

+0

+1000 Riduzione di formula brillante. –

1

Wow! Argomento e soluzione ottimali per evitare l'uso di "set datefirst 1". Voglio solo aggiungere qualcosa. Se come me, vuoi anche restituire l'anno con la settimana ISO, come "2015-01" come "Anno 2015, Settimana 01", potrebbe essere utile per scopi di reporting. Dal momento che l'anno dalla settimana ISO può essere diverso dall'anno effettivo della data! Ecco come ho fatto in combinazione con il tuo codice.

DECLARE @Date AS DATETIME 
SET @Date = '2014-12-31' 
SELECT 
     CAST(CASE WHEN MONTH(@Date) = 1 AND Q.ISOweek > 50 THEN YEAR(@Date) - 1 
       WHEN MONTH(@Date) = 12 AND Q.ISOweek < 3 THEN YEAR(@Date) + 1 
       ELSE YEAR(@Date) 
      END 
      AS VARCHAR(4)) 
    + '-' 
    + RIGHT('00' + CAST(Q.ISOweek AS NVARCHAR(2)), 2) AS ISOweek 
FROM (SELECT (datepart(DY, datediff(d, 0, @Date)/7 * 7 + 3) + 6)/7 AS ISOweek) Q 

tornerai "2015-01".

+1

Ho già scritto un semplice script per iso_year. http://stackoverflow.com/questions/22829604/what-is-iso-year-in-sql-server/22830524#22830524 –

0

Avevo bisogno di qualcosa di simile per PowerQuery & PowerBI e in base alla risposta di t-clausen.dk sono riuscito a rendere questa equazione. Funziona come il suo ma usa la sintassi di PowerQuery. Anche il data base per il DATEDIFF di 0 era 1/1/1900 in SQL ma in PowerQuery è 12/30/1899 per cui uso 2 al posto del 0.

ISO Week = Number.RoundDown((Date.DayOfYear(Date.From(Duration.Days(([Date]-Date.From(2))/7)*7+5))+6)/7) 

Ho anche bisogno dell'anno ISO in modo ho fatto un adeguamento al calcolo settimana ISO e si avvicinò con:

ISO Year = Date.Year(Date.From(Duration.Days(([Date]-Date.From(2))/7)*7+3)) 

Modificare il [Date] per fare riferimento alla colonna della data nei dati.

Problemi correlati