powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Cгенерить все вторники в заданном диапазоне
8 сообщений из 33, страница 2 из 2
Cгенерить все вторники в заданном диапазоне
    #40081485
Посетитель
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
spenov,
максимальный нужный номер легко вычисляется при известном диапазоне дат.
...
Рейтинг: 0 / 0
Cгенерить все вторники в заданном диапазоне
    #40082162
Wlr-l
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
iap
Wlr-l
Я уже начал волноваться, почему iap до сих пор не привел решение с формулой дня недели, не зависящей от настроек сервера? Спасибо, я успокоился.
Можно было в FAQ подсмотреть!
Я там тоже писал...


Спасибо, в следующий раз обязательно загляну!

Правда, я сказал, что вторники здесь ни_при_чём. Хотел показать, что основой для решения таких задач является известный со школы алгоритм: решето Эратосфена. Причем все основные вычисления в этом решении проводятся с числами и только на последнем этапе формируются даты. Причем, в отличии от чистого решета Эратосфена, генерируется столько строк, сколько нужно сгенерировать дат.

Посетитель тоже проникся духом Эратосфена и даже автоматизировал получение базового вторника.
...
Рейтинг: 0 / 0
Cгенерить все вторники в заданном диапазоне
    #40082175
Посетитель
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Wlr-l,
решето Эратосфена, это взять весь календарь, удалить оттуда понедельники, потом среды и т.д.
...
Рейтинг: 0 / 0
Cгенерить все вторники в заданном диапазоне
    #40082176
Wlr-l
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Посетитель
Wlr-l,
решето Эратосфена, это взять весь календарь, удалить оттуда понедельники, потом среды и т.д.

Зачем так много действий? Берете известный вторник и после него обводите кружком каждую седьмую дату, в оригинале выдавливаете их (отсюда и появилось решето).
...
Рейтинг: 0 / 0
Cгенерить все вторники в заданном диапазоне
    #40082182
Посетитель
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Wlr-l

Зачем так много действий?


потому что алгоритм такой. взять полный набор и итерационным путем убирать лишнее.

а мое решение к решету никакого отношения не имеет.
...
Рейтинг: 0 / 0
Cгенерить все вторники в заданном диапазоне
    #40082451
Wlr-l
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Посетитель,

" потому что алгоритм такой. взять полный набор и итерационным путем убирать лишнее ".

Эратосфен решал задачу нахождения простых чисел, и вы правильно заметили, что в этом случае требуются итерации. Если взять одну итерацию, то в ней он отмечал числа, начиная с определенного числа, через соответствующие равные промежутки.

Мы решаем другую задачу: находим вторники. Для этого достаточно одной такой итерации.

Каждая итерация у Эратосфена начинается с определенного числа.
Нахождение вторников также начинается с определенного вторника.

Эратосфен отмечал числа путем зачеркивания (выдавливал ненужное), а я предложил отмечать числа кружком (выдавливать нужное) ( 22341307 ). Это несущественное отличие.

Вы делаете упор на организацию цикла, а я – на тело цикла.

" а мое решение к решету никакого отношения не имеет "

Вы можете считать так, это ваше право. Но есть вопрос: "Чем ваше решение отличается от моего ( 22342687 ), которое было дано раньше?".
Мое решение:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
declare @tueBase date = '20201229';
with
 l0(n) as (select 0 union all select 0 union all select 0 union all select 0 union all select 0 union all select 0 union all select 0 union all select 0), 
 l1(n) as (select 0 from l0 t1 cross join l0 t2),
 l2(n) as (select 0 from l1 t1 cross join l1 t2),
 r(n)  as (select row_number() over(order by (select 0)) * 7 from l2),
 D(d)  as (select dateadd(day, n, @tueBase) from r)
select *
  from d
 where d between '20210701' and '20210731';


Ваше решение:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
DECLARE @D1 DATE='20210207', @D2 DATE='20211213', @W TINYINT=1 /*вторник*/;
with w as (Select*from(values(0),(1),(2),(3),(4),(5),(6))a(d))
 ,n as (select row_number()over(order by 1/0)-1 r from w,w a,w b,w c,w d,w e) 
 select dateadd(week,r,FirstTue)
   from n
       ,(Select dateadd(dd,d,@D1) FirstTue
           from w
          where datepart(dw,dateadd(dd,d,@D1))=datepart(dw,@W))x
  where dateadd(week,r,FirstTue)<=@D2;


В том, что я взял готовый базовый вторник, чтобы не загромождать пример, а вы его вычислили. Все остальное тождественно. Так я уже сказал, что вы "автоматизировали получение базового вторника".

Там же я привел рекурсивный вариант, который "переоткрыл" ваш собеседник.

И, если уж автоматически формировать базовый вторник, то
1) если взять не первый вторник после даты @D1, а последний вторник перед этой датой, то в запросе n можно убрать -1
2) лучше не вычислять часть даты от целого числа (datepart(dw, @W) – что это такое?), а воспользоваться советом iap :
Код: sql
1.
2.
3.
select dateadd(dd, -d, @D1) as FirstTue
   from (values (0), (1), (2), (3), (4), (5), (6)) as a(d)
  where (@@datefirst+datepart(weekday, dateadd(day, -d, @D1))-2)%7=@W



На этом у меня все по этой теме.
...
Рейтинг: 0 / 0
Cгенерить все вторники в заданном диапазоне
    #40082509
Посетитель
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Wlr-l,

ну если замена итерационного подхода на неитерационный - это несущественные отличия, то вообще любой sql-запрос, содержащий предикат, это решето Эратосфена

что уж говорить о замене фильтрации на генерацию. это, видимо, тоже идентичные алгоритмы)



Wlr-l
"Чем ваше решение отличается от моего ( 22342687 ), которое было дано раньше?


принципиально - ничем. ни от вашего, ни от решения iap. И все они одинаково далеки от алгоритма, на который вы пытаетесь их натянуть.


Wlr-l
datepart(dw, @W) – что это такое?

это просто альтернативный способ получить (@@datefirst+datepart(weekday, dateadd(day, -d, @D1))-2)%7=@W без проверки настройки @@datefirst
...
Рейтинг: 0 / 0
Cгенерить все вторники в заданном диапазоне
    #40082786
Wlr-l
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Посетитель,

1. Идеи, заложенные в решете Эратосфена, оказали влияние лично на меня в плане понимания обработки периодических данных. Конечно, не только и исключительно эти.

Если вы считаете, что разработали уникальный алгоритм нахождения вторников, который не имеет предшественников, то я ни на что не претендую.

2. На решение написать это сообщение повлиял сегодняшний вопрос о разных результатах функции datepart(weekday, @DateFrom). Казалось бы, всё здесь уже оговорено, но такой вопрос периодически звучит. Вы написали:

datepart(dw, @W) – это просто альтернативный способ получить (@@datefirst+datepart(weekday, dateadd(day, -d, @D1))-2)%7=@W без проверки настройки @@datefirst.

Это не совсем так:
Код: sql
1.
2.
3.
4.
5.
DECLARE @W TINYINT=1 /*вторник*/;
set datefirst 7;
select @@DATEFIRST, datepart(dw, @W), (@@datefirst+datepart(weekday, @W)-2)%7;
set datefirst 1;
select @@DATEFIRST, datepart(dw, @W), (@@datefirst+datepart(weekday, @W)-2)%7;


7 3 1
1 2 1

Т.е. это не альтернативные способы несмотря на то, что в вашем решении получаем нужный результат.

Плюс к этому, новые типы данных для представления дат уже не воспринимают числа в качестве даты. С точки зрения строгой типизации операция взятия части даты от целого числа должна вызывать ошибку синтаксического разбора. Поэтому вместо 1 можно взять любой вторник, например,
Код: sql
1.
DECLARE @W  date = '19000102' /*в этот день был вторник*/;


и это будет понятней.

В вашем решении все-таки нужно заранее знать хотя бы одну дату вторника, а в решении iap достаточно знать константу дня недели.

Таким образом, эти два решения не альтернативны.

Теперь у меня точно всё, чтобы вторники не начали сниться по ночам.
...
Рейтинг: 0 / 0
8 сообщений из 33, страница 2 из 2
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Cгенерить все вторники в заданном диапазоне
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]