Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

combinando dados mensais de futuros com séries temporais do mês anterior no MySQL


É preciso muita pré-verificação, mas, em essência, tive que construir variáveis ​​SQL com base em um passo de cada vez, como se estivesse em um programa de "let X =alguma coisa", "let y =X + outra coisa" , etc. Ao construir as variáveis ​​@SQLVars mais internas, uma vez que a primeira é declarada, ela pode ser usada como base da próxima variável e assim por diante... Primeiro, aqui está a consulta completa que você pode aplicar aos seus dados que compila com base em qualquer que seja a data atual. Você conhecendo melhor seus dados pode ter que ajustá-los um pouco, mas acho que isso o deixa bem no seu caminho.
select
      CONCAT( 'Q (', LEFT( MonthName( DateBasis.dMonth1 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth1 ), 2 ), ')' ) as FirstMonth,
      CONCAT( 'U (', LEFT( MonthName( DateBasis.dMonth2 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth2 ), 2 ), ')' ) as SecondMonth,
      CONCAT( 'V (', LEFT( MonthName( DateBasis.dMonth3 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth3 ), 2 ), ')' ) as ThirdMonth,
      CONCAT( 'X (', LEFT( MonthName( DateBasis.dMonth4 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth4 ), 2 ), ')' ) as FourthMonth
   from   
      ( select @FirstOfMonth dFirstOfMonth,
               @FDOM nWeekDay,
               @SWOM nSecondWedOfMonth,
               @SkipMonths nSkip,
               @Month1 dMonth1,
               @Month2 dMonth2,
               @Month3 dMonth3,
               @Month4 dMonth4
           from
              ( select @FirstOfMonth := CONCAT( year(curdate()), '-', month( curdate()), '-01' ),
                       @FDOW := DayOfWeek( @FirstOfMonth ),
                       @SWOM := if( @FDOW <= 4, 12, 19) - @FDOW,
                       @SkipMonths := if( day( CurDate()) <= @SWOM, 1, 2 ),
                       @Month1 := date_add( @FirstOfMonth, interval 0 +  @SkipMonths month ),
                       @Month2 := date_add( @Month1, interval 1 month ),
                       @Month3 := date_add( @Month2, interval 1 month ),
                       @Month4 := date_add( @Month3, interval 1 month )
                       ) sqlvars
      ) DateBasis

O resultado desta consulta acima retornará um registro SINGLE (com base na data atual de 31 de janeiro) para mostrarFirstMonth SecondMonth ThirdMonth FourthMonthQ (12 de março) U (12 de abril) V (12 de maio) X (12 de junho)

Agora, aninhe isso dentro do restante de sua consulta para seus IDs de ticker, algo como
SELECT hist.date, 
       hist.ticker_id, 
       hist.settle_price, 
       hist.volume 
   FROM 
      hist,
      ( entire select statement above ) FinalDates

   WHERE 
          hist.ticker_id IN ( FinalDates.FirstMonth,
                              FinalDates.SecondMonth,
                              FinalDates.ThirdMonth,
                              FinalDates.FourthMonth )
      and hist.trade_dt = curdate()

Se você olhar para o @SqlVariables mais interno, como mencionado anteriormente, é como um monte de "let x=something". Eu sempre preciso de uma base para começar, então primeiro estou obtendo o primeiro dia de um determinado mês em uma variável @FirstOfMonth fazendo uma concatenação de qualquer que seja o ano da data atual + "-" + mês da data atual + "-01" para sempre começar no primeiro dia do mês... ex:Hoje é 31 de janeiro de 2012 irá construir uma string de '2012-01-01' que no formato ano/mês/data é imediatamente reconhecida pelo MySQL como um formato de data, podemos realizar aritmética de data. Então agora, eu tenho @FirstOfMonth ='2012-01-01'. Agora, precisamos determinar o primeiro dia da semana que esta data representa do mês em que estamos (daí @FDOW). Isso retornará um valor de 1 a 7 (domingo =1, qua =4, sáb =7).

A partir disso, agora precisamos calcular quando será a 2ª quarta-feira do mês. Se o dia da semana for de domingo a (inclusive) quarta-feira, a SEGUNDA quarta-feira terá 12 dias MENOS o dia da semana. Ex:Domingo dia 1 seria qua 4, então qua dia 11... então 12 - 1 (domingo) =11. Se o primeiro dia do mês fosse uma quarta, seria um dia da semana =4, mas o 1º do mês =qua, o segundo qua =8, então 12 - 4 =8. Agora, se a data fosse qui, sex ou sáb como o primeiro do mês, o dia da semana seria 5, 6 ou 7 . A data MÍNIMA da primeira quarta-feira seria 7, a segunda qua seria 14, então isso está começando com 19 - qualquer dia da semana... 5, 6, 7... Ex:19 - 5(Qui Dia de Semana) =14, 19 - 6 (Sex Dia da Semana) =13, 19 - 7 (Sáb Dia da Semana) =12 be é 7 e 14 em oposição a 1 e 8 (mais cedo do mês).

Agora que sabemos QUANDO é a segunda quarta-feira do mês, compare isso com a data em que estamos executando a consulta com base (ou seja:curdate() ). Se a data atual for ON ou ANTES (via <=) da SEGUNDA QUARTA do MÊS (@SWOM), então só queremos pular mais de 1 mês... se estivermos mais no mês, precisamos pular 2 meses.

Agora, construa as datas. A base de data para o Mês 1 é o primeiro do mês atual MAIS um intervalo de quantos meses para pular. O mês 2 é um mês após o primeiro, o mês 3 um mês após o mês 2 e o mês 4 um mês após o mês 3.
@FirstOfMonth := CONCAT( year(curdate()), '-', month( curdate()), '-01' ),
@FDOW := DayOfWeek( @FirstOfMonth ),
@SWOM := if( @FDOM <= 4, 12, 19) - @FDOM,
@SkipMonths := if( day( CurDate()) <= @SWOM, 1, 2 ),
@Month1 := date_add( @FirstOfMonth, interval 0 +  @SkipMonths month ),
@Month2 := date_add( @Month1, interval 1 month ),
@Month3 := date_add( @Month2, interval 1 month ),
@Month4 := date_add( @Month3, interval 1 month )

Então, finalmente temos todos os 4 meses de base para trabalhar em uma única linha de (select ...) conjunto de resultados sqlvars mostrando algo como
@Month1     @Month2     @Month3     @Month4
2012-03-01  2012-04-01  2012-05-01  2012-06-01 ... the four months out

Finalmente, uma vez que esses dados pareçam corretos, agora podemos construir as strings específicas que você está procurando com os respectivos prefixos "Q", "U", "V" e "X" mais os 3 à esquerda do nome do mês com os 2 dígito ano.

Portanto, com isso obtendo todos os intervalos de datas e strings que você espera, consulte isso em sua outra tabela, conforme listei na inicial.

Espero que isso ajude você e abra seus olhos para um contexto completamente novo para enganar o SQL para... em essência fazer um programa inline para criar muitas variáveis ​​e operar a partir disso... Muito legal hein...

E com toda a veracidade, esta é a primeira vez que tentei especificamente essa técnica, embora tenha feito muitas consultas no passado usando SQLVars.