Para responder por que você está recebendo uma segunda-feira e não um domingo:
Você está adicionando um número de semanas à data 0. O que é a data 0? 1900-01-01. Qual foi o dia 01/01/1900? Segunda-feira. Então, em seu código, você está dizendo, quantas semanas se passaram desde segunda-feira, 1º de janeiro de 1900? Vamos chamar isso de [n]. Ok, agora adicione [n] semanas a segunda-feira, 1 ° de janeiro de 1900. Você não deve se surpreender que isso acaba sendo uma segunda-feira. DATEADD
não tem ideia de que você deseja adicionar semanas, mas apenas até chegar a um domingo, é apenas adicionar 7 dias, depois adicionar mais 7 dias, ... assim como DATEDIFF
apenas reconhece os limites que foram ultrapassados. Por exemplo, ambos retornam 1, embora algumas pessoas reclamem que deve haver alguma lógica sensata embutida para arredondar para cima ou para baixo:
SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');
Para responder como conseguir um domingo:
Se você quiser um domingo, escolha uma data base que não seja segunda-feira, mas sim um domingo. Por exemplo:
DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);
Isso não será interrompido se você alterar sua DATEFIRST
configuração (ou se seu código estiver sendo executado para um usuário com uma configuração diferente) - desde que você ainda queira um domingo, independentemente da configuração atual. Se você quer que essas duas respostas para jive, então você deve usar uma função que não dependem da DATEFIRST
configuração, por exemplo,
SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
Portanto, se você alterar sua DATEFIRST
configuração para segunda, terça-feira, o que for, o comportamento mudará. Dependendo de qual comportamento você deseja, você pode usar uma destas funções:
CREATE FUNCTION dbo.StartOfWeek1 -- always a Sunday
(
@d DATE
)
RETURNS DATE
AS
BEGIN
RETURN (SELECT DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @d), '19050101'));
END
GO
...ou...
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
Agora, você tem muitas alternativas, mas qual tem o melhor desempenho? Ficaria surpreso se houvesse grandes diferenças, mas reuni todas as respostas fornecidas até agora e as executei em dois conjuntos de testes - um barato e outro caro. Eu medi as estatísticas do cliente porque não vejo a E / S ou a memória desempenhando um papel no desempenho aqui (embora elas possam ser importantes dependendo de como a função é usada). Em meus testes, os resultados são:
Consulta de atribuição "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 atribuição "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
Posso retransmitir os detalhes dos meus testes, se desejar - parando aqui, pois isso já está ficando muito prolixo. Fiquei um pouco surpreso ao ver o Curt sair como o mais rápido no topo, devido ao número de cálculos e código embutido. Talvez eu execute alguns testes mais completos e blog sobre isso ... se vocês não têm nenhuma objeção a eu publicar suas funções em outro lugar.
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
permanece constante, independentemente da@@datefirst
configuração, eu acho. Com segunda-feira = 2.