Semana do mês (mas de acordo com a semana do calendario)

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
brauliomsf
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qui, 18 Out 2007 9:18 am
Localização: SP
Braulio Moizes

Olá
alguém sabe teria uma function ou sql mesmo que me mostre a semana do mês mas com base no calendario, ou seja:

outubro de 2008 : semana 1 seria do dia 1 a 4
semana 2 seria do dia 5 a 11 e assim por diante

usando to_char(data_qualquer,'W') mostra a semana do mês mas sempre quebrando de 7 em 7 , ou seja: semana1 (do dia 1 ao 7), semana 2 (do dia 8 ao 14).....

Grato
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Olha só:
Fiz uma tabela que contém datas de 1 até o outro mês:

Selecionar tudo

select trunc(to_date('01-mar-2008'),'mm')+rownum-1 dt  
      from all_objects
      where rownum<=35
Ou seja:

Selecionar tudo

SQL> select trunc(to_date('01-mar-2008'),'mm')+rownum-1 dt
  2        from all_objects
  3        where rownum<=35
  4  /

DT
---------
01-MAR-08
02-MAR-08
03-MAR-08
04-MAR-08
05-MAR-08
06-MAR-08
07-MAR-08
08-MAR-08
09-MAR-08
10-MAR-08
11-MAR-08
12-MAR-08
13-MAR-08
14-MAR-08
15-MAR-08
16-MAR-08
17-MAR-08
18-MAR-08
.
.
.
Agora que temos essa tabela, eu fiz assim:

Selecionar tudo

SELECT 
  dt 
, TO_CHAR( dt, 'DY' , 'NLS_DATE_LANGUAGE=PORTUGUESE' ) dia  
, CASE 
  WHEN dt - 8+TO_CHAR(  TRUNC(dt,'MM'), 'D') <  TRUNC(dt,'MM')  THEN 1
  ELSE TO_CHAR (dt - 8+TO_CHAR(  TRUNC(dt,'MM'), 'D') , 'W')+1     
  END semana

FROM (SELECT TRUNC(TO_DATE('01-MAR-2008'),'MM')+ROWNUM-1 dt  
      FROM all_objects
      WHERE ROWNUM<=35
     )
Vamos aos testes:

Selecionar tudo

SQL> SELECT 
  2    dt 
  3  , TO_CHAR( dt, 'DY' , 'NLS_DATE_LANGUAGE=PORTUGUESE' ) dia  
  4  , CASE 
  5    WHEN dt - 8+TO_CHAR(  TRUNC(dt,'MM'), 'D') <  TRUNC(dt,'MM')  THEN 1
  6    ELSE TO_CHAR (dt - 8+TO_CHAR(  TRUNC(dt,'MM'), 'D') , 'W')+1     
  7    END semana
  8  FROM (SELECT TRUNC(TO_DATE('01-MAR-2008'),'MM')+ROWNUM-1 dt  
  9        FROM all_objects
 10        WHERE ROWNUM<=35
 11       )
 12  /

DT        DIA           SEMANA
--------- --------- ----------
01-MAR-08 SAB                1
02-MAR-08 DOM                2
03-MAR-08 SEG                2
04-MAR-08 TER                2
05-MAR-08 QUA                2
06-MAR-08 QUI                2
07-MAR-08 SEX                2
08-MAR-08 SAB                2
09-MAR-08 DOM                3
10-MAR-08 SEG                3
11-MAR-08 TER                3

DT        DIA           SEMANA
--------- --------- ----------
12-MAR-08 QUA                3
13-MAR-08 QUI                3
14-MAR-08 SEX                3
15-MAR-08 SAB                3
16-MAR-08 DOM                4
17-MAR-08 SEG                4
18-MAR-08 TER                4
19-MAR-08 QUA                4
20-MAR-08 QUI                4
21-MAR-08 SEX                4
22-MAR-08 SAB                4

DT        DIA           SEMANA
--------- --------- ----------
23-MAR-08 DOM                5
24-MAR-08 SEG                5
25-MAR-08 TER                5
26-MAR-08 QUA                5
27-MAR-08 QUI                5
28-MAR-08 SEX                5
29-MAR-08 SAB                5
30-MAR-08 DOM                6
31-MAR-08 SEG                6
01-APR-08 TER                1
02-APR-08 QUA                1

DT        DIA           SEMANA
--------- --------- ----------
03-APR-08 QUI                1
04-APR-08 SEX                1

35 rows selected.

SQL> 
Vamos para outro mês qualquer (JUNHO):

Selecionar tudo

SQL> SELECT 
  2    dt 
  3  , TO_CHAR( dt, 'DY' , 'NLS_DATE_LANGUAGE=PORTUGUESE' ) dia  
  4  , CASE 
  5    WHEN dt - 8+TO_CHAR(  TRUNC(dt,'MM'), 'D') <  TRUNC(dt,'MM')  THEN 1
  6    ELSE TO_CHAR (dt - 8+TO_CHAR(  TRUNC(dt,'MM'), 'D') , 'W')+1     
  7    END semana
  8  FROM (SELECT TRUNC(TO_DATE('01-jun-2008'),'MM')+ROWNUM-1 dt  
  9        FROM all_objects
 10        WHERE ROWNUM<=35
 11       )
 12  /

DT        DIA           SEMANA
--------- --------- ----------
01-JUN-08 DOM                1
02-JUN-08 SEG                1
03-JUN-08 TER                1
04-JUN-08 QUA                1
05-JUN-08 QUI                1
06-JUN-08 SEX                1
07-JUN-08 SAB                1
08-JUN-08 DOM                2
09-JUN-08 SEG                2
10-JUN-08 TER                2
11-JUN-08 QUA                2

DT        DIA           SEMANA
--------- --------- ----------
12-JUN-08 QUI                2
13-JUN-08 SEX                2
14-JUN-08 SAB                2
15-JUN-08 DOM                3
16-JUN-08 SEG                3
17-JUN-08 TER                3
18-JUN-08 QUA                3
19-JUN-08 QUI                3
20-JUN-08 SEX                3
21-JUN-08 SAB                3
22-JUN-08 DOM                4

DT        DIA           SEMANA
--------- --------- ----------
23-JUN-08 SEG                4
24-JUN-08 TER                4
25-JUN-08 QUA                4
26-JUN-08 QUI                4
27-JUN-08 SEX                4
28-JUN-08 SAB                4
29-JUN-08 DOM                5
30-JUN-08 SEG                5
01-JUL-08 TER                1
02-JUL-08 QUA                1
03-JUL-08 QUI                1

DT        DIA           SEMANA
--------- --------- ----------
04-JUL-08 SEX                1
05-JUL-08 SAB                1

35 rows selected.

SQL> 
Provavelmente deve existir um jeito mais fácil!!!
Esse tópico sempre me ajuda nessa horas:
http://glufke.net/oracle/viewtopic.php?t=22

:-o
margaridi
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 21
Registrado em: Ter, 08 Abr 2008 11:09 am
Localização: Curitiba - PR
Contato:
----------------------------
Margaridi, Marco Aurélio
www.margaridi.com

Criei uma função para te ajudar.
Segue abaixo o código da mesma e um exemplo de uso.
Se tiver dúvidas, mande msg.
Abraço.

Selecionar tudo

declare

vCurrentWeek number(1);
vWeek1       number(2);
vWeek2       number(2);
vWeek3       number(2);
vWeek4       number(2);
vWeek5       number(2);

--------------------------------------------------------------------------
-- Function fFindWeek
-- A partir de uma data qualquer, a função calcula a semana atual, de 
-- acordo com o calendário comercial, sendo que cada semana começa
-- no domingo e termina no sábado
--------------------------------------------------------------------------
-- Desenvolvedor: Margaridi, Marco Aurélio (marco@margaridi.com)
-- Data         : 04/11/2008
--------------------------------------------------------------------------
-- Parâmetros:

-- ffw_date_to_test    in  date   -- a data a ser testada
-- ffw_week_1_last_day out number -- o último dia da primeira semana 
-- ffw_week_2_last_day out number -- o último dia da segunda semana   
-- ffw_week_3_last_day out number -- o último dia da terceira semana   
-- ffw_week_4_last_day out number -- o último dia da quarta semana   
-- ffw_week_5_last_day out number -- o último dia da quinta semana   
                                  -- ou ZERO se o mês só possuir 4 semanas
-- A função retorna a semana da data informada
--------------------------------------------------------------------------
function fFindWeek(ffw_date_to_test in date
                  ,ffw_week_1_last_day out number
                  ,ffw_week_2_last_day out number 
                  ,ffw_week_3_last_day out number
                  ,ffw_week_4_last_day out number
                  ,ffw_week_5_last_day out number) return number is
  vWeekControl    number(1) := 0;
  vWeekDay        number(1);
  vMonthDay       number(2);
  vLastDay        date;
  vFirstDay       date;
  vDayToTest      date;
  vResult         number;

begin

  select last_day(sysdate)
  into   vLastDay
  from   dual;
  
  vFirstDay  := to_date('01'||to_char(vLastDay,'mmyyyy'),'ddmmyyyy');
  vDayToTest := trunc(ffw_date_to_test);
  
  while vFirstDay < vLastDay loop
  

     select to_number(to_char(vFirstDay,'d'),'9')
     ,      to_number(to_char(vFirstDay,'dd'),'99')
     into   vWeekDay
     ,      vMonthDay
     from   dual;
     
     if vFirstDay = vDayToTest then
        vResult := vWeekControl + 1;
     end if;
     
     if vWeekDay = 7 then
     
        vWeekControl := vWeekControl + 1;
        
        case vWeekControl 
           when 1 then ffw_week_1_last_day := vMonthDay;
           when 2 then ffw_week_2_last_day := vMonthDay;
           when 3 then ffw_week_3_last_day := vMonthDay;
           when 4 then ffw_week_4_last_day := vMonthDay;
           when 5 then ffw_week_5_last_day := vMonthDay;
        end case;
           
     end if;
  
     vFirstDay := vFirstDay + 1;
  
  end loop;
  
  ffw_week_5_last_day := vMonthDay;

  if vWeekControl = 3 then
     ffw_week_4_last_day := vMonthDay;
     ffw_week_5_last_day := 0;
  end if;

  return(vResult);

end ffindweek;
--------------------------------------------------------------------------
-- Function fFindWeek (END)
--------------------------------------------------------------------------

begin
   vCurrentWeek := ffindWeek(sysdate,vWeek1,vWeek2,vWeek3,vWeek4,vWeek5);
   dbms_output.put_line(to_char(vCurrentWeek)||' | '||to_char(vWeek1)
                                             ||' | '||to_char(vWeek2)
                                             ||' | '||to_char(vWeek3)
                                             ||' | '||to_char(vWeek4)
                                             ||' | '||to_char(vWeek5));
end;

leodamian
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 3
Registrado em: Sex, 22 Jan 2021 10:17 am
Localização: SOROCABA

Bom dia,
Estava procurando exatamente isso, extrair o numero da semana do mês. Mas fiquei com uma dúvida na query, o que significa " dt - 8 ", o que seria o 8 ?
CASE
WHEN dt - 8+TO_CHAR( TRUNC(dt,'MM'), 'D') < TRUNC(dt,'MM') THEN 1
ELSE TO_CHAR (dt - 8+TO_CHAR( TRUNC(dt,'MM'), 'D') , 'W')+1
END semana

Obrigado pelo Post.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 18 visitantes