Para responder por qué tiene un lunes y no un domingo:
Está agregando un número de semanas a la fecha 0. ¿Qué es la fecha 0? 1900-01-01. ¿Qué día fue el 01/01/1900? Lunes. Entonces, en su código está diciendo, ¿cuántas semanas han pasado desde el lunes 1 de enero de 1900? Llamemos a eso [n]. Bien, ahora agregue [n] semanas al lunes 1 de enero de 1900. No debería sorprenderse de que termine siendo lunes. DATEADD
no tiene idea de que desea agregar semanas, pero solo hasta que llegue un domingo, solo agrega 7 días, luego agrega 7 días más, ... al igual que DATEDIFF
solo reconoce los límites que se han cruzado. Por ejemplo, ambos devuelven 1, aunque algunas personas se quejan de que debería haber alguna lógica sensata incorporada para redondear hacia arriba o hacia abajo:
SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');
Para responder cómo conseguir un domingo:
Si desea un domingo, elija una fecha base que no sea un lunes sino un domingo. Por ejemplo:
DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);
Esto no se interrumpirá si cambia su DATEFIRST
configuración (o su código se está ejecutando para un usuario con una configuración diferente), siempre que aún desee un domingo independientemente de la configuración actual. Si quieres esas dos respuestas a jive, entonces usted debe utilizar una función que no dependen de la DATEFIRST
configuración, por ejemplo,
SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
Entonces, si cambia su DATEFIRST
configuración a lunes, martes, lo que sea, el comportamiento cambiará. Según el comportamiento que desee, puede utilizar una de estas funciones:
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
Ahora, tiene muchas alternativas, pero ¿cuál funciona mejor? Me sorprendería si hubiera diferencias importantes, pero recopilé todas las respuestas proporcionadas hasta ahora y las ejecuté a través de dos conjuntos de pruebas: una barata y otra costosa. Medí las estadísticas del cliente porque no veo que la E / S o la memoria desempeñen un papel en el rendimiento aquí (aunque pueden entrar en juego dependiendo de cómo se use la función). En mis pruebas los resultados son:
Consulta de asignación "barata":
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
Consulta de asignación "cara":
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
Puedo transmitir los detalles de mis pruebas si lo deseo, deteniéndome aquí, ya que esto ya se está volviendo bastante largo. Me sorprendió un poco ver a Curt salir como el más rápido en el extremo superior, dada la cantidad de cálculos y el código en línea. Tal vez haga algunas pruebas más exhaustivas y escribo un blog al respecto ... si ustedes no tienen ninguna objeción a que publique sus funciones en otro lugar.
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
permanece constante independientemente del@@datefirst
entorno, creo. Con lunes = 2.