4
respostas

Gerar somente dados de Semestre e Ano

Pessoal, boa noite. Como eu utilizo o script do professor somente para gerar informações de Semestre e Ano? Eu mexi no declare e no insert para somente esses dados, porém ainda estou com problemas, pois é gerado mais valores do que eu preciso. Segue script abaixo:

DECLARE @DIMDATE TABLE
    (    
        [COD_TEMPO] INT PRIMARY KEY IDENTITY (1,1),
        [COD_SEMESTRE] NVARCHAR(50),
        [DESC_SEMESTRE] NVARCHAR(50),
        [COD_SEMESTRE_ANO] NVARCHAR(50),
        [DESC_SEMESTRE_ANO] NVARCHAR(50),
        [ANO] NVARCHAR(50)
    )

DECLARE @AnoInicial VARCHAR(4) = '2014'
DECLARE @MesInicial VARCHAR(2) = '1'
DECLARE @AnoFinal VARCHAR(4) = '2020'
DECLARE @MesFinal VARCHAR(2) = '6'

DECLARE @StartDate DATETIME
Select @StartDate = CAST(@AnoInicial + '/' + @MesInicial + '/01' AS DATETIME)

DECLARE @EndDate DATETIME 
SELECT @EndDate = DATEADD(month, ((CAST(@AnoFinal AS INTEGER) - 1900) * 12) + CAST(@MesFinal AS INTEGER), 0)

DECLARE
    @DayOfWeekInMonth INT,
    @DayOfWeekInYear INT,
    @DayOfQuarter INT,
    @WeekOfMonth INT,
    @CurrentYear INT,
    @CurrentMonth INT,
    @CurrentQuarter INT

DECLARE @DayOfWeek TABLE (DOW INT, MonthCount INT, QuarterCount INT, YearCount INT)

INSERT INTO @DayOfWeek VALUES (1, 0, 0, 0)
INSERT INTO @DayOfWeek VALUES (2, 0, 0, 0)
INSERT INTO @DayOfWeek VALUES (3, 0, 0, 0)
INSERT INTO @DayOfWeek VALUES (4, 0, 0, 0)
INSERT INTO @DayOfWeek VALUES (5, 0, 0, 0)
INSERT INTO @DayOfWeek VALUES (6, 0, 0, 0)
INSERT INTO @DayOfWeek VALUES (7, 0, 0, 0)

DECLARE @CurrentDate AS DATETIME = @StartDate
SET @CurrentMonth = DATEPART(MM, @CurrentDate)
SET @CurrentYear = DATEPART(YY, @CurrentDate)
SET @CurrentQuarter = DATEPART(QQ, @CurrentDate)

WHILE @CurrentDate < @EndDate
BEGIN

    IF @CurrentMonth != DATEPART(MM, @CurrentDate) 
    BEGIN
        UPDATE @DayOfWeek
        SET MonthCount = 0
        SET @CurrentMonth = DATEPART(MM, @CurrentDate)
    END

    IF @CurrentQuarter != DATEPART(QQ, @CurrentDate)
    BEGIN
        UPDATE @DayOfWeek
        SET QuarterCount = 0
        SET @CurrentQuarter = DATEPART(QQ, @CurrentDate)
    END

    IF @CurrentYear != DATEPART(YY, @CurrentDate)
    BEGIN
        UPDATE @DayOfWeek
        SET YearCount = 0
        SET @CurrentYear = DATEPART(YY, @CurrentDate)
    END

    UPDATE @DayOfWeek
    SET 
        MonthCount = MonthCount + 1,
        QuarterCount = QuarterCount + 1,
        YearCount = YearCount + 1
    WHERE DOW = DATEPART(DW, @CurrentDate)

    SELECT
        @DayOfWeekInMonth = MonthCount,
        @DayOfQuarter = QuarterCount,
        @DayOfWeekInYear = YearCount
    FROM @DayOfWeek
    WHERE DOW = DATEPART(DW, @CurrentDate)

    INSERT INTO @DIMDATE
    SELECT    
        CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN '01'
            WHEN 2 THEN '01'
            WHEN 3 THEN '02'
            WHEN 4 THEN '02'
            END 
            AS COD_SEMESTRE,
            CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN 'Primeiro Semestre'
            WHEN 2 THEN 'Primeiro Semestre'
            WHEN 3 THEN 'Segundo Semestre'
            WHEN 4 THEN 'Segundo Semestre'
            END 
            AS DESC_SEMESTRE,
            CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN '01'
            WHEN 2 THEN '01'
            WHEN 3 THEN '02'
            WHEN 4 THEN '02'
            END + '-' + 
            CONVERT(NVARCHAR(4), DATEPART(YEAR, @CurrentDate)) as COD_SEMESTRE_ANO,
            CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN 'Primeiro Semestre'
            WHEN 2 THEN 'Primeiro Semestre'
            WHEN 3 THEN 'Segundo Semestre'
            WHEN 4 THEN 'Segundo Semestre'
            END + ' ' + 
            CONVERT(NVARCHAR(4), DATEPART(YEAR, @CurrentDate)) as DESC_SEMESTRE_ANO,
            CONVERT(NVARCHAR(4), DATEPART(YEAR, @CurrentDate)) AS ANO

    SET @CurrentDate = DATEADD(DD, 1, @CurrentDate)
END

SELECT * FROM @DIMDATE order by COD_TEMPO

Poderiam me ajudar?

4 respostas

Oi Guilherme, tudo bem?

Eu rodei o script para ver e também fiz umas modificações removendo variáveis e funções que não precisa. No caso para trazer apenas o Ano e o Semestre teríamos que fazer um outro script, pois esse que o professor utiliza ele faz com base na data. Por isso que é retornado várias linhas, pois cada uma delas é um dia do mês e por aí vai.

Não sei como é a regra de negócio para o que está utilizando esse script, mas seria interessante manter a data. Para que depois for solicitado a data, não precise mexer na estrutura da tabela.

Segue o script atualizado:

DECLARE @DIMDATE TABLE
    (    
        [COD_TEMPO] INT PRIMARY KEY IDENTITY (1,1),
        [DATA] DATE,
        [COD_SEMESTRE] NVARCHAR(50),
        [DESC_SEMESTRE] NVARCHAR(50),
        [COD_SEMESTRE_ANO] NVARCHAR(50),
        [DESC_SEMESTRE_ANO] NVARCHAR(50),
        [ANO] NVARCHAR(50)
    )

DECLARE @AnoInicial VARCHAR(4) = '2014'
DECLARE @MesInicial VARCHAR(2) = '1'
DECLARE @AnoFinal VARCHAR(4) = '2020'
DECLARE @MesFinal VARCHAR(2) = '6'

DECLARE @StartDate DATETIME
Select @StartDate = CAST(@AnoInicial + '/' + @MesInicial + '/01' AS DATETIME)

DECLARE @EndDate DATETIME 
SELECT @EndDate = DATEADD(month, ((CAST(@AnoFinal AS INTEGER) - 1900) * 12) + CAST(@MesFinal AS INTEGER), 0)

DECLARE
    @CurrentYear INT,
    @CurrentMonth INT,
    @CurrentQuarter INT

DECLARE @CurrentDate AS DATETIME = @StartDate
SET @CurrentMonth = DATEPART(MM, @CurrentDate)
SET @CurrentYear = DATEPART(YY, @CurrentDate)
SET @CurrentQuarter = DATEPART(QQ, @CurrentDate)

WHILE @CurrentDate < @EndDate
BEGIN

     INSERT INTO @DIMDATE
    SELECT    
    @CurrentDate as Data,
        CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN '01'
            WHEN 2 THEN '01'
            WHEN 3 THEN '02'
            WHEN 4 THEN '02'
            END 
            AS COD_SEMESTRE,
            CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN 'Primeiro Semestre'
            WHEN 2 THEN 'Primeiro Semestre'
            WHEN 3 THEN 'Segundo Semestre'
            WHEN 4 THEN 'Segundo Semestre'
            END 
            AS DESC_SEMESTRE,
            CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN '01'
            WHEN 2 THEN '01'
            WHEN 3 THEN '02'
            WHEN 4 THEN '02'
            END + '-' + 
            CONVERT(NVARCHAR(4), DATEPART(YEAR, @CurrentDate)) as COD_SEMESTRE_ANO,
            CASE DATEPART(QQ, @CurrentDate)
            WHEN 1 THEN 'Primeiro Semestre'
            WHEN 2 THEN 'Primeiro Semestre'
            WHEN 3 THEN 'Segundo Semestre'
            WHEN 4 THEN 'Segundo Semestre'
            END + ' ' + 
            CONVERT(NVARCHAR(4), DATEPART(YEAR, @CurrentDate)) as DESC_SEMESTRE_ANO,
            CONVERT(NVARCHAR(4), DATEPART(YEAR, @CurrentDate)) AS ANO

    SET @CurrentDate = DATEADD(DD, 1, @CurrentDate)
END

SELECT * FROM @DIMDATE order by COD_TEMPO

Qualquer dúvida estou por aqui, tá bom? :)

Maria, muito obrigado pelo rápido retorno!

Na verdade estamos trabalhando com um DW para uma escola, onde na fato temos somente informações de Semestre e Ano, e não informações mensais por exemplo. Na regra de negócio deles é preciso somente Semestre e Ano. Na hora de fazer a ligação dessa dimensão com a fato, vai haver repetição nos dados uma vez que o COD_SEMESTRE_ANO "01-2014" por exemplo possui 181 registros na tabela.

Seguindo essa ideia, de 2373 registros que a tabela possui, passaria a ter 13:

01/2014 02/2014 01/2015 02/2015 01/2016 02/2016 01/2017 02/2017 01/2018 02/2018 01/2019 02/2019 01/2020

Por gentileza, poderia me auxiliar ou me dar um direcionamento?}

Muito obrigado desde já!

Oi Guilherme, tudo bom?

Desculpa pela demora em retornar, pois eu estava tentando fazer um script da dimensão tempo de uma forma que guardasse apenas o semestre e o ano sem repetir os dias.

Acontece que de toda forma que eu tentei fazer, precisei da data e foi guardado mês a mês. O máximo que cheguei foi a isso:

CREATE TABLE [DimTempo](
      [Ano] [smallint] NOT NULL,
      [MesNumero] [smallint] NOT NULL,
      [Semestre] [smallint] NOT NULL

)

DECLARE @Ano smallint
DECLARE @Data smalldatetime
DECLARE @DataIni smalldatetime
DECLARE @DataFim smalldatetime
DECLARE @MesNumero smallint
DECLARE @Semestre smallint

SET @DataIni='01/01/2014'
SET @DataFim='30/06/2020'

SET @Data=@DataIni
While @Data<=@DataFim
Begin
     Set @MesNumero = month(@Data)
     Select @Semestre= Case
          when @MesNumero in (1,2,3,4,5,6) then 1
          when @MesNumero in (7,8,9,10,11,12) then 2
     End
     Set @Ano = YEAR(@Data)

     INSERT INTO DimTempo values(@Ano, @MesNumero, @Semestre)

     Select @Data= case
     when @MesNumero in (1,3,5,7,8,10,12) then dateadd(day,31,@Data)
     when @MesNumero in (4,6,9,11) then dateadd(day,30,@Data)
     when @MesNumero = 2 then dateadd(day,28,@Data)
     End

End

Ao meu ver, não faz muito sentido na dimensão tempo guardar apenas o semestre e o ano. A dimensão é uma tabela dimensional, ou seja, podemos ter vários dados guardados ali dentro sem problema algum. O interessante, seria ao montar o dashboard, você utilizar apenas a coluna do semestre ou ano-semestre para poder fazer as análises.

Peço imensas desculpas por não conseguir te dar um direcionamento certeiro para guardar apenas o semestre e ano, mas acredito que dessa forma já te ajude bastante.

Se eu puder ajudar em algo mais, estou à disposição sempre, tá bom? :)

Maria, boa tarde! Tudo bem e com você?

Achei uma maneira de inserir apenas semestre e ano. Estou utilizando o componente "Classificar". Desta forma, a query é mantida e caso algum dia precise de todos os meses, basta retirar esse componente que a dimensão tempo será carregada por completo.

Você me ajudou bastante com esses dois scripts e com certeza é bom ter esses dados mês a mês pois se um dia a regra de negócio mudar, não precisarei refazer o script.

Agradeço pela disponibilidade e ajuda!

Tenha um ótimo dia! :)