sql server - How To Shorten This SQL Query Without A Million AND/OR's? -
i have table 13 columns (one row id # , other 12 represent 1 each month of year). each column contain numbers , want write several queries check each row conditions , return id of rows match.
so far i've been fine writing basic select queries i'm getting bit stuck on writing select queries check multiple conditions @ once without writing million lines of code each time.
the current query i'm writing needs check each pair of consecutive months (e.g. jan/feb, feb/mar, etc) see how big difference between them , needs return rows 2 lots of consecutive months have > 20% difference between them , remaining pairs < 10% difference.
for example, if january 1000 , february 1300, that's 30% difference that's 1 lot. if april 1500 , may 2100, that's 40% difference there's 2nd lot. long every other pair (feb/mar, mar/apr, ..., nov/dec) < 10% difference each, row needs returned.
unfortunately, way can work manually checking every single possibility (which works) isn't re-useable writing similar queries.
here abbreviated version of i've got far:
select pkid dbo.tblmonthdata ((colfeb > coljan * 1.2 , colmar > colfeb * 1.2) , (colapr < colmar * 1.1 , colmay < colapr * 1.1 , coljun < colmay * 1.1 , coljul < coljun * 1.1 , colaug < coljul * 1.1 , colsep < colaug * 1.1 , coloct < colsep * 1.1 , colnov < coloct * 1.1 , coldec < colnov * 1.1)) or ((colfeb > coljan * 1.2 , colapr > colmar * 1.2) , (colmar < colfeb * 1.1 , colmay < colapr * 1.1 , coljun < colmay * 1.1 , coljul < coljun * 1.1 , colaug < coljul * 1.1 , colsep < colaug * 1.1 , coloct < colsep * 1.1 , colnov < coloct * 1.1 , coldec < colnov * 1.1)) or ((colfeb > coljan * 1.2 , colmay > colapr * 1.2) , (colmar < colfeb * 1.1 , colapr < colmar * 1.1 , coljun < colmay * 1.1 , coljul < coljun * 1.1 , colaug < coljul * 1.1 , colsep < colaug * 1.1 , coloct < colsep * 1.1 , colnov < coloct * 1.1 , coldec < colnov * 1.1)) ... or ((colnov > coloct * 1.2 , coldec > colnov * 1.2) , (colfeb < coljan * 1.1 , colmar < colfeb * 1.1 , colapr < colmar * 1.1 , colmay < colapr * 1.1 , coljun < colmay * 1.1 , coljul < coljun * 1.1 , colaug < coljul * 1.1 , colsep < colaug * 1.1 , coloct < colsep * 1.1))
in total there 55 lines of or statements check every possible combination of this. if went query similar (e.g. return row id #'s 2 pairs greater 50% , 4 pairs under 10%), involves writing long query scratch checking every other possible combination.
so wondering how re-write in shorter version more re-useable similar queries?
so, alternate answer @pieter's answer , illustrate how simpler data structure may make task easier, suggest following:
create view tbleasy ( select pkid, 1 colmonth, coljan colvalue tblmonthdata union select pkid, 2 colmonth, colfeb colvalue tblmonthdata union select pkid, 3 colmonth, colmar colvalue tblmonthdata union select pkid, 4 colmonth, colapr colvalue tblmonthdata union select pkid, 5 colmonth, colmay colvalue tblmonthdata union select pkid, 6 colmonth, coljun colvalue tblmonthdata union select pkid, 7 colmonth, coljul colvalue tblmonthdata union select pkid, 8 colmonth, colaug colvalue tblmonthdata union select pkid, 9 colmonth, colsep colvalue tblmonthdata union select pkid, 10 colmonth, coloct colvalue tblmonthdata union select pkid, 11 colmonth, colnov colvalue tblmonthdata union select pkid, 12 colmonth, coldec colvalue tblmonthdata );
this makes view how have structured table initially. easy create pairs comparing value on colmonth
on colmonth + 1
.
i made fiddle illustrate how comparing done in view, , query if obvious.
http://sqlfiddle.com/#!3/600f6/4
note performance not great due initial table structure.
update since being accepted answer, embed details sqlfiddle.
extra view pre-calculate difference between consecutive months:
create view tblpairs ( select t1.pkid , t1.colmonth colstart, (t2.colvalue * 100 / t1.colvalue) colpercentage tbleasy t1 inner join tbleasy t2 on t1.pkid = t2.pkid , t1.colmonth = t2.colmonth - 1);
query find 2 months have on 20% increase , other 9 have less 10%:
select distinct pkid tblpairs t1 2 = ( select count(*) tblpairs t2 t2.pkid = t1.pkid , colpercentage >= 120) , 9 = ( select count(*) tblpairs t2 t2.pkid = t1.pkid , colpercentage <= 110) ;
Comments
Post a Comment