|
Программирование >> Преобразование значений null
01-JUN-2005 Далее, используя функцию MONTH, получаем месяц текущей даты и с помощью простого выражения CASE определяем, является ли первый день этого месяца понедельником или нет: select dy, month(dy) mth, case when dayname(dy)=Monday then 1 else 0 end is monday from ( select (current date-day(current date) day +1 day) dy from t1 ) tmp1 DY MTH IS MONDAY 01-JUN-2005 6 0 После этого используем рекурсивные возможности оператора WITH и последовательно добавляем по одному дню, начиная с первого дня месяца, до тех пор пока не дойдем до первого дня следующего месяца. В ходе этого с помощью выражения CASE отбираем понедельники (отмечая их флагом 1 ). Результат рекурсивного представления Х частично показан ниже: with x (dy,mth,is monday) as ( select dy,month(dy) mth, case when dayname(dy)=Monday then 1 else 0 end is monday from ( select (current date-day(current date) day +1 day) dy from t1 ) tmp1 union all select (dy +1 day), mth, case when dayname(dy +1 day)=Monday then 1 else 0 end from x where month(dy +1 day) = mth вычитания 10 из 10-го апреля будем иметь последний день марта). После этого вычитания просто добавляем один день, чтобы получить первый день текущего месяца: select (current date-day(current date) day +1 day) dy from t1 select * from x DY MTH IS MONDAY 01-JUN-2005 6 0 02-JUN-2005 6 0 03-JUN-2005 6 0 04-JUN-2005 6 0 05-JUN-2005 6 0 06-JUN-2005 6 1 07-JUN-2005 6 0 08-JUN-2005 6 0 Значения 1 столбца IS MONDAY будут соответствовать понедельникам. Таким образом, заключительный шаг - применяя агрегатные функции MIN и MAX к строкам, в которых значение поля IS MON-DAY равно 1, находим первый и последний понедельники месяца. Oracle Функция NEXT DAY значительно упрощает решение этой задачи. Чтобы найти первый понедельник текущего месяца, сначала посредством некоторых вычислений с привлечением функции TRUNC возвращаем последний день предыдущего месяца: select trunc(sysdate,mm)-1 dy from dual 31-MAY-2005 Затем используем функцию NEXT DAY, чтобы найти первый понедельник после последнего дня предыдущего месяца (т. е. первый понедельник текущего месяца): select next day(trunc(sysdate,mm)-1,MONDAY) first monday from dual FIRST MONDAY 06-JUN-2005 Чтобы найти последний понедельник текущего месяца, сначала с помощью функции TRUNC возвращаем первый день текущего месяца: select trunc(sysdate,mm) dy from dual 01-JUN-2005 23-JUN-2005 Здесь мы возвращаемся на семь дней от последнего дня месяца, чтобы гарантированно получить, по крайней мере, по одному разу каждый день недели. Последний шаг - использовать функцию NEXT DAY, чтобы найти следующий (и последний) понедельник месяца: select next day(last day(trunc(sysdate,mm))-7,MONDAY) last monday from dual LAST MONDAY 27-JUN-2005 PostgreSQL и MySQL В PostgreSQL и MySQL используется аналогичный подход, отличие состоит лишь в вызываемых функциях. Cоответствующие запросы предельно просты, несмотря на их размеры; некоторые издержки возникают при поиске первого и последнего понедельников текущего месяца. Первый шаг - найти первый день текущего месяца. Следующий шаг -определить первый понедельник месяца. Поскольку специальной функции, которая возвращала бы следующую дату, соответствующую заданному дню недели, нет, необходимо прибегнуть к небольшим вычислениям. Выражение CASE, начинающееся в строке 7 (любого решения), вычисляет разницу между числовым значением дня недели первого дня месяца и числовым значением, соответствующим понедельнику. Исходя из того, что функция TO CHAR (PostgresSQL) с форматной маской D или d и функция DAYOFWEEK (MySQL) для дней недели от воскресенья до субботы возвращают числовые значения от 1 до 7, понедельник всегда будет представлен цифрой 2. Сначала выражение CASE проверяет знак (SIGN) полученной разности между первым днем месяца (каким бы он ни был) и числовым значением понедельника (2). Если результат равен 0, первый день месяца выпадает на понедельник, и это первый понедельник месяца. Если результат равен -1, первый день месяца выпадает на воскресенье, и чтобы найти первый понедельник, надо просто добавить в первому дню месяца разницу в днях между 2 и 1 (числовые значения понедельника и воскресенья соответственно). Если возникают сложности с пониманием логики этих операций, забудьте о названиях дней недели и оперируйте только числами. Например, пусть первым днем месяца является Следующий шаг - находим последнюю неделю (последние семь дней) месяца. С помощью функции LAST DAY получаем последний день месяца и вычитаем семь дней: select last day(trunc(sysdate,mm))-7 dy from dual
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |