Per rispondere al motivo per cui hai un lunedì e non una domenica:
Stai aggiungendo un numero di settimane alla data 0. Cos'è la data 0? 1900-01-01. Qual è stato il giorno del 1900-01-01? Lunedi. Quindi nel tuo codice stai dicendo, quante settimane sono passate da lunedì 1 gennaio 1900? Chiamiamolo [n]. Ok, ora aggiungi [n] settimane a lunedì 1 gennaio 1900. Non dovresti sorprenderti se questo finisce per essere un lunedì. DATEADD
non ha idea che tu voglia aggiungere settimane ma solo fino ad arrivare a una domenica, aggiunge solo 7 giorni, quindi aggiungi altri 7 giorni, ... proprio come DATEDIFF
riconosce solo i confini che sono stati oltrepassati. Ad esempio, entrambi restituiscono 1, anche se alcune persone si lamentano del fatto che dovrebbe esserci una logica ragionevole incorporata per arrotondare per eccesso o per difetto:
SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');
Per rispondere a come ottenere una domenica:
Se vuoi una domenica, scegli una data di base che non sia un lunedì ma piuttosto una domenica. Per esempio:
DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);
Ciò non si interromperà se modifichi l' DATEFIRST
impostazione (o il codice è in esecuzione per un utente con un'impostazione diversa), a condizione che tu voglia comunque una domenica indipendentemente dall'impostazione corrente. Se si desidera che queste due risposte a jive, allora si dovrebbe utilizzare una funzione che non dipendono dalla DATEFIRST
impostazione, ad esempio,
SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
Quindi, se modifichi l' DATEFIRST
impostazione su lunedì, martedì, cosa hai, il comportamento cambierà. A seconda del comportamento che desideri, puoi utilizzare una di queste funzioni:
CREATE FUNCTION dbo.StartOfWeek1 -- always a Sunday
(
@d DATE
)
RETURNS DATE
AS
BEGIN
RETURN (SELECT DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @d), '19050101'));
END
GO
...o...
CREATE FUNCTION dbo.StartOfWeek2 -- always the DATEFIRST weekday
(
@d DATE
)
RETURNS DATE
AS
BEGIN
RETURN (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, @d), @d));
END
GO
Ora, hai molte alternative, ma quale funziona meglio? Sarei sorpreso se ci fossero differenze importanti, ma ho raccolto tutte le risposte fornite finora e le ho eseguite attraverso due serie di test: uno economico e uno costoso. Ho misurato le statistiche del cliente perché non vedo l'I / O o la memoria che giocano un ruolo nelle prestazioni qui (sebbene queste possano entrare in gioco a seconda di come viene utilizzata la funzione). Nei miei test i risultati sono:
Query di assegnazione "economica":
Function - client processing time / wait time on server replies / total exec time
Gandarez - 330/2029/2359 - 0:23.6
me datefirst - 329/2123/2452 - 0:24.5
me Sunday - 357/2158/2515 - 0:25.2
trailmax - 364/2160/2524 - 0:25.2
Curt - 424/2202/2626 - 0:26.3
Query di assegnazione "costosa":
Function - client processing time / wait time on server replies / total exec time
Curt - 1003/134158/135054 - 2:15
Gandarez - 957/142919/143876 - 2:24
me Sunday - 932/166817/165885 - 2:47
me datefirst - 939/171698/172637 - 2:53
trailmax - 958/173174/174132 - 2:54
Posso trasmettere i dettagli dei miei test, se lo desideri, fermandomi qui perché sta già diventando piuttosto prolisso. Sono rimasto un po 'sorpreso di vedere che Curt è uscito come il più veloce nella fascia alta, dato il numero di calcoli e il codice in linea. Forse eseguirò alcuni test più approfonditi e ne parlerò sul blog ... se voi ragazzi non avete obiezioni a che pubblichi le vostre funzioni altrove.
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
rimane costante indipendentemente@@datefirst
dall'impostazione credo. Con lunedì = 2.