итерационный подход, основанный на PL/SQL PIPELINED
functions:
CREATE OR REPLACE TYPE days_tbl AS TABLE OF DATE;
CREATE OR REPLACE FUNCTION days_for_month(basedate IN DATE)
RETURN days_tbl PIPELINED
AS
month VARCHAR(2);
thedate DATE := TRUNC(basedate,'MON');
BEGIN
LOOP
PIPE ROW(thedate);
EXIT WHEN thedate = LAST_DAY(thedate);
thedate := thedate + 1;
END LOOP;
END;
Основы использования:
SELECT COLUMN_VALUE
FROM TABLE(days_for_month(SYSDATE))
WHERE TO_CHAR(COLUMN_VALUE,'FMDAY') = 'MONDAY';
Функция может быть оптимизирована для ваших конкретных потребностей (найти заданный день по имени), но держать его более общий характер позволяет некоторую гибкость использования, как:
SELECT COLUMN_VALUE
FROM TABLE(days_for_month(SYSDATE))
WHERE TO_CHAR(COLUMN_VALUE,'FMDAY') IN ('SUNDAY','SATURDAY');
Учитывая ваш пример:
«Сколько понедельников, понедельников и пятниц (или любых дней) в сентябре 2015 года?».
SELECT COUNT(*)
FROM TABLE(days_for_month(TO_DATE('09-2015','MM-YYYY')))
WHERE TO_CHAR(COLUMN_VALUE,'FMDAY') IN ('MONDAY','TUESDAY','FRIDAY');
Производство:
COUNT(*)
13
Или, если вам нужна деталь:
SELECT T.D, COUNT(*)
FROM TABLE(days_for_month(TO_DATE('09-2015','MM-YYYY'))),
(SELECT 'MONDAY' AS D FROM DUAL UNION
SELECT 'TUESDAY' FROM DUAL UNION
SELECT 'FRIDAY' FROM DUAL) T
WHERE TO_CHAR(COLUMN_VALUE,'FMDAY') = T.D
GROUP BY T.D
Для производства:
D COUNT(*)
TUESDAY 5
FRIDAY 4
MONDAY 4
Вы могли бы написать скрипт, который проверяет, что в первый день месяца, и сколько дней в месяце и экстраполировать оттуда. – Leeish