Отнема много предварителна проверка, но по същество трябваше да изградя SQL променливи въз основа на една стъпка в даден момент, сякаш беше в програма от "нека X =нещо", "нека y =X + нещо друго" , и т.н. Чрез изграждането на повечето вътрешни променливи @SQLVars, след като първата е декларирана, тя може да се използва като основа на следващата променлива и така нататък... Първо, ето пълната заявка, която можете да приложите към вашите данни, които изграждат въз основа на каквато и да е текущата дата. Познавайки данните си по-добре, може да се наложи да ги настроите малко, но мисля, че това ще ви помогне да вървите добре.
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
Резултатът от тази една заявка по-горе ще върне ЕДИНСТВЕН запис (въз основа на текущата дата 31 януари) за показванеFirstMonth SecondMonth ThirdMonth FourthMonthQ (12 март) U (12 април) V (12 май) X (12 юни)
Сега вложете това в останалата част от вашата заявка за вашите идентификационни номера на тикер, нещо като
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()
Ако погледнете най-вътрешните @SqlVariables, както бе споменато по-рано, е като куп "нека x=нещо". Винаги имам нужда от база, за да започна, така че първо получавам първия ден от даден месец в променлива @FirstOfMonth, като правя конкатенация на каквато и да е годината на текущата дата + "-" + месец на текущата дата + "-01" винаги да започва на първо число на месеца... напр.:Днес е 31 януари 2012 г. ще изгради низ от '2012-01-01', който във формат година/месец/дата се разпознава незабавно от MySQL като формат на дата можем да извършваме аритметика за дата. Така че сега имам @FirstOfMonth ='2012-01-01'. Сега трябва да определим първия ден от седмицата, който тази дата представлява от месеца, в който се намираме (следователно @FDOW). Това ще върне стойност от 1-7 (неделя =1, сряда =4, събота =7).
От това сега трябва да изчислим кога ще бъде 2-та сряда от месеца. Ако денят от седмицата е от неделя до (включително) сряда, ВТОРАТА сряда е 12 дни МИНУС денят от седмицата. Например:1-ва неделя ще бъде сряда 4-та, след това сряда 11-та... така че 12 - 1 (неделя) =11. Ако първият ден от месеца е сряда, това ще бъде ден от седмицата =4, но 1-во число на месеца =ср., втората ср. =8, така че 12 - 4 =8. Сега, ако датата е била четвъртък, петък или събота като първи от месеца, денят от седмицата ще бъде 5, 6 или 7 МИНИМАЛНАТА дата на първата сряда ще бъде 7, втората сряда ще бъде 14, така че това започва с 19 - независимо от деня от седмицата... 5, 6, 7... Напр.:19 - 5 (четвъртък ден от Седмица) =14, 19 - 6 (петък ден от седмицата) =13, 19 - 7 (събота ден от седмицата) =12.. И така, знаем, че първата сряда ще бъде цялата седмица, така че най-ранната ще бъде be е 7-мо и 14-о число, за разлика от 1-во и 8-мо (най-ранното от месеца).
Сега, когато знаем КОГА е 2-та сряда от месеца, сравнете това с датата, на която изпълняваме заявката въз основа (т.е. curdate() ). Ако текущата дата е ВКЛЮЧЕНА или ПРЕДИ (чрез <=) ВТОРАТА СРЕДА на МЕСЕЦА (@SWOM), тогава искаме да пропуснем само 1 месец... ако сме по-нататък в месеца, трябва да пропуснем 2 месеца.
Сега изградете датите. Базата за дата за месец 1 е първият от текущия месец ПЛЮС интервал от толкова месеци, който трябва да се пропусне. Месец 2 е един месец след първия, месец 3 един след месец 2 и месец 4 един след месец 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 )
Така че най-накрая имаме всички 4-месечни бази, с които да работим в един ред (изберете ...) sqlvars набор от резултати, показващ нещо като
@Month1 @Month2 @Month3 @Month4
2012-03-01 2012-04-01 2012-05-01 2012-06-01 ... the four months out
И накрая, след като тези данни изглеждат добре, вече можем да изградим конкретните низове, които търсите със съответните префикси "Q", "U", "V" и "X", плюс лявото 3 от името на месеца с 2 цифрена година.
Така че, като получите всички периоди от време и низове, които очаквате, потърсете това спрямо другата си таблица, както посочих в началото.
Надявам се това да ви помогне и да ви отвори очите за напълно нов контекст, за да подмамите SQL да... по същество правите вградена програма, за да създадете много променливи и да работите от това... Доста готино нали...
И честно казано, това е първият път, когато изпробвам специално тази техника, въпреки че в миналото съм правил много заявки с помощта на SQLVars.