CHill60
Я создал следующие тестовые данные, чтобы продемонстрировать, что вам нужно сделать - это просто ряд дат с числом для представления некоторых данных
create table #test
(
datadate date,
data int
)
declare @startdate date = '2018-05-01'
declare @enddate date = getdate()
;WITH q AS
(
SELECT @startdate AS d1, 1 as d2
UNION ALL
SELECT dateadd(d, 1, d1) , d2 + 1
FROM q
WHERE dateadd(d, 1, d1) < @enddate
)
INSERT INTO #test
SELECT d1, d2
FROM q
Получить "вчерашние" данные несложно:
SELECT * FROM #test
WHERE datadate = DATEADD(d, -1, cast(getdate() as date))
То
CAST
это просто чтобы избавиться от элемента времени
getdate()
в противном случае данные не возвращаются.
Чтобы получить номер недели я использую встроенный
DATEPART
функция с параметром
week
. Е. Г.
select * FROM #test
WHERE (DATEPART(week,datadate)- DATEPART(week,DATEADD(m, DATEDIFF(m, 0, datadate), 0))) + 1 = 3
Чтобы определить, какой сегодня день недели, я не буду использовать слово "понедельник" и т. д., Поскольку это зависит от языка. Я собираюсь использовать индекс или номер дня в течение недели. Но это зависит от вашей установки
@@DATEFIRST
Люке Ат
эта должность[
^] обеспечивает хорошее решение:
select *, DATENAME(dw, datadate), DATEPART(dw, datadate) FROM #test
WHERE ((DATEPART(dw, datadate) + @@DATEFIRST) % 7) NOT IN (0, 1)
Теперь вам нужно собрать все это вместе. Вы могли бы использовать
CASE
в
WHERE
да, но я не фанатка. В приведенном ниже примере я использую CTE (Common Table Expression), чтобы сначала определить, сколько дней назад я хочу включить, а затем использовать
BETWEEN
в простом виде
WHERE
пункт. Вы должны заменить его
getdate()
для
@testdate
в приведенном ниже коде:
declare @testdate date = '2018-06-12' -- '2018-05-7' -- Monday -- monday of 3rd week '2018-06-11' -- tuesday '2018-06-12'
;with q1 as
(
select datadate, data
,daysback = CASE WHEN ((DATEPART(dw, @testdate) + @@DATEFIRST) % 7) = 2 AND (DATEPART(week,@testdate)- DATEPART(week,DATEADD(m, DATEDIFF(m, 0, @testdate), 0))) + 1 = 3 THEN
-- Monday of 3rd week so we want Fri, Sat, Sun ... this date minus 3 days
-3
WHEN ((DATEPART(dw, @testdate) + @@DATEFIRST) % 7) = 2 THEN
-- any other monday so we want Sat and Sun
-2
ELSE
-- any other day so just yesterday
-1
END
from #test
)
SELECT *
from q1
WHERE datadate BETWEEN dateadd(d, daysback, @testdate) AND dateadd(d, -1, @testdate)
[Редактировать после ОП комментарий]
(Любой, кто думает, что 3 - й понедельник месяца - это то же самое, что и понедельник 3-й недели, должен рассмотреть, как вы определяете первую неделю месяца-это первая целая неделя, начинающаяся в определенный день-обычно воскресенье или понедельник, или это с 1-го по 7-е число месяца независимо от дня)
Чтобы иметь 3-й понедельник месяца, а не понедельник 3-й недели, то используйте это в
CASE
WHEN ((DATEPART(dw, @testdate) + @@DATEFIRST) % 7) = 2 AND ceiling(DAY(@testdate) / 7.0) = 3 THEN
-3
Пояснение: Мы обсуждали это
((DATEPART(dw, @testdate) + @@DATEFIRST) % 7) = 2
найдете "понедельники". Дополнительный бит можно объяснить, разбив его на части:
DAY(@testdate)
собирается вернуть день месяца, например сегодня 18 на 18 июня 2018 года. Деление этого числа на количество дней в неделе дает вам представление о том, на какой неделе оно находится. Например, 18 / 7.0 дает 2.571428. Обратите внимание на 7
.0, в противном случае 18/7 дает ответ 2. Вы можете интерпретировать это 2.571428 как "у нас уже было целых 2 понедельника в этом месяце, и теперь мы частично входим в следующий". Итак, добавив
ceiling
мы можем определить, что "следующий" на самом деле является
3-е место Понедельник (для этого месяца).
Ладно, это, вероятно, не самое лучшее объяснение, но, надеюсь, вы можете видеть, что происходит.
В качестве отступления (и заслуги), это было адаптировано из поста Линн Петтис, у которой есть много полезных вещей в ее блоге
SQL размышления из пустыни[
^] на SQL сервера.