Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Вземете първия ден от седмицата в SQL Server

За да отговорите защо получавате понеделник, а не неделя:

Добавяте няколко седмици към датата 0. Какво е дата 0? 1900-01-01. Какъв беше денят на 01.01.1900 г.? понеделник. Така че във вашия код вие казвате колко седмици са минали от понеделник, 1 януари 1900 г.? Да наречем това [n]. Добре, сега добавете [n] седмици към понеделник, 1 януари 1900 г. Не бива да се учудвате, че това в крайна сметка е понеделник. DATEADD няма представа, че искате да добавите седмици, но само докато стигнете до неделя, това е просто добавяне на 7 дни, след това добавяне на още 7 дни, ... точно като DATEDIFF разпознава само границите, които са били преминати. Например и двете връщат 1, въпреки че някои хора се оплакват, че трябва да има някаква разумна логика, вградена за закръгляване нагоре или надолу:

SELECT DATEDIFF(YEAR, '2010-01-01', '2011-12-31');
SELECT DATEDIFF(YEAR, '2010-12-31', '2011-01-01');

За да отговорите как да получите неделя:

Ако искате неделя, тогава изберете основна дата, която не е понеделник, а по-скоро неделя. Например:

DECLARE @dt DATE = '1905-01-01';
SELECT [start_of_week] = DATEADD(WEEK, DATEDIFF(WEEK, @dt, CURRENT_TIMESTAMP), @dt);

Това няма да се счупи, ако промените своя DATEFIRST настройка (или кодът ви се изпълнява за потребител с различна настройка) - при условие, че все още искате неделя, независимо от текущата настройка. Ако искате тези два отговора да са джайв, тогава трябва да използвате функция, която прави зависи от DATEFIRST настройка, напр.

SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);

Така че, ако промените своя DATEFIRST настройване на понеделник, вторник, какво имаш, поведението ще се промени. В зависимост от това какво поведение искате, можете да използвате една от тези функции:

CREATE FUNCTION dbo.StartOfWeek1 -- always a Sunday
(
    @d DATE
)
RETURNS DATE
AS
BEGIN
    RETURN (SELECT DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @d), '19050101'));
END
GO

...или...

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

Сега имате много алтернативи, но коя се представя най-добре? Бих се изненадал, ако има някакви големи разлики, но събрах всички предоставени досега отговори и ги прокарах през два комплекта тестове - един евтин и един скъп. Измерих клиентска статистика, защото не виждам I/O или паметта да играят роля в производителността тук (въпреки че те могат да влязат в действие в зависимост от това как се използва функцията). В моите тестове резултатите са:

„Евтина“ заявка за присвояване:

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

„Скъпа“ заявка за присвояване:

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

Мога да предам подробности за моите тестове, ако желаете - спирам тук, тъй като това вече става доста дълготрайно. Бях малко изненадан да видя, че Curt's излезе като най-бърз във високия клас, като се има предвид броя на изчисленията и вградения код. Може би ще направя някои по-задълбочени тестове и ще направя блог за това... ако вие нямате възражения да публикувам функциите ви на друго място.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Вземете AVG, пренебрегвайки Null или Zero стойности

  2. Защо имената на таблици в SQL Server започват с dbo?

  3. Използване на GO в рамките на транзакция

  4. Схема на SQL сървър и схема по подразбиране

  5. Автоматизиране на тестовото възстановяване на базата данни в SQL Server