Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Complicated SQL - can we make it?
Message
General information
Forum:
Visual FoxPro
Category:
Databases,Tables, Views, Indexing and SQL syntax
Miscellaneous
Thread ID:
00437328
Message ID:
00438080
Views:
14
Hi Ko,

First of all, thanks for the code, you provided. I will use it.
Secondly, now I misled you :) You misunderstood me.
I have two separate applications: one is for selecting records from our database (actually, there are even two of them for the first purpose: btCrit - user selection screen - my own application, but was started by my colleague and Query - my colleague application) and Statistics (the application, I'm now working on). First application allows us to select records from our database by different criteria, specified by user. The second application should perform various statistics calculation based on saved statistics configuration in a MetaFile. It's not clear for me, how this should be done (I man using saved configuration), so I started from trying to create a simple statistics (then I'll try to generalize this code).

So, suppose we selected records by these criteria: County: Norfolk and Essex; sale date between 10/01/1997 and 11/31/2000.
First of all, I think, we have to create a table (or cursor) with all possible periods, IOW:
select min(cYear+cMonth) as cMinYearMonth, max(cYear+cMonth) as cMaxYearMonth from InputTable into cursor curTemp
create table tblPeriods free (cYearMonth C(6), cYear C(4), cMonth C(2))
select curTemp
m.cYearMonth=cMinYearMonth
m.cYear=left(cMinYearMonth,4)
lnMinYear=val(lcMinYear)
m.cMonth=right(cMinYearMonth,2)
lnMinMonth=val(lcMinMonth)
lcMaxYear=left(cMaxYearMonth,4)
lnMaxYear=val(lcMaxYear)
lcMaxMonth=right(cMaxYearMonth,2)
lnMaxMonth=val(lcMaxMonth)
use in curTemp && Close temp cursor
do while .t.
  insert into tblPeriods from memvar && First min record
  if lnMinYear=lnMaxYear and lnMinMonth=lnMaxMonth 
     exit
  endif
  if lnMinMonth=12
     lnMinMonth=0
     lnMinYear=lnMinYear+1
  endif
  lnMinMonth=lnMinMonth+1
  m.cMonth=padl(lnMinMonth,2,'0')
  m.cYear=str(lnMinYear,4)
  m.cYearMonth=m.cYear+m.cMonth
enddo

Now I have all possible periods in tblPeriods table and may continue with your code.

<sup>*</sup> All this code I wrote from the top of my head, so it's not necessary the best way...

>>Thanks, Ko. Yes, a simple typo led to a problem :)
>>
>>BTW, the problem turns to be a little bit more complicated.
>>Suppose, I select records from our database for this period of time:
>>06/01/1997 to 11/30/2000
>>
>>I'd like to have data on each possible period: each month, each quoter, each year in this time frame. How can I create a table with all these periods (I can not garantee, that all these periods would be in selected result).
><hr>
>The last thing you can't do with your first solution (not having all periods)
>
>I've done my best and here is the result.
>Please take a look at it, and tell me if it is what you need.
>The data i used is below the code.
>
>Code follows:<hr>
><pre>ldFirstDate = {^1999-01-11}
>ldLastDate = {^2001-01-11}
>** The above should be parameters
>Local lcOldCentury, lcOldDate,; && Old Settings
>	lcFirstMonth, lcLastMonth  && Variables for selecting a date range
>
>lcOldCentury = Set('Century')
>lcOldDate = Set('Date')
>Set Date American
>Set Century On
>
>lcFirstMonth = Right(DTOC(ldFirstDate),4) + Left(DTOC(ldFirstDate),2)
>lcLastMonth  = Right(DTOC(ldLastDate) ,4) + Left(DTOC(ldLastDate) ,2)
>
>Set Date &lcOldDate
>Set Century &lcOldCentury
>
>** Preselections
>** These are used later for determining what has to be selected
>Select Distinct cYear;
>	From InputTable;
>	Order By cYear;
>	Where cYear+cMonth between lcFirstMonth and lcLastMonth;
>		; && Probably You want the full year here but that's easy to change
>	Into Table tmpYear
>Select Distinct cYear,cQtr;
>	From InputTable;
>	Where cYear+cMonth between lcFirstMonth and lcLastMonth;
>		; && Probably You want the full Quater here but that's easy to change
>	Order By cYear,cQtr;
>	Into Table tmpQtr
>Select Distinct cYear,cMonth;
>	From InputTable;
>	Where cYear+cMonth between lcFirstMonth and lcLastMonth;
>		; && The day was not in the table, so i think you want this.
>	Order By cYear,cMonth;
>	Into Table tmpMonth
>
>#IF .F. && The three seperate select statements.
>** Set the above to .T. to let them run
>** The empty values are for the union thing later on.
>	Select cCode, cTown, tmpYear.cYear, '  ' as cQtr, '  ' as cMonth,;
>			Sum(iPrice) as YtdVol, Count(*) as YtdNum,;
>			tmpYear.cYear as tmpOrder;
>		From tmpYear, InputTable;
>		Where InputTable.cYear = tmpYear.cYear and;
>			InputTable.cYear+cMonth between lcFirstMonth and lcLastMonth;
>			; && Probably You want the full Year here but that's easy to change
>			; && This where clause is also added here, because otherwise all months of the
>			; && year are included
>		Group By cCode, cTown, tmpOrder
>		
>	Select cCode, cTown, tmpQtr.cYear, tmpQtr.cQtr, '  ' as cMonth,;
>			Sum(iPrice) as YtdVol, Count(*) as YtdNum,;
>			tmpQtr.cYear+tmpQtr.cQtr as tmpOrder;
>		From tmpQtr, InputTable;
>		Where InputTable.cYear = tmpQtr.cYear and;
>			InputTable.cQtr between '01' and tmpQtr.cQtr and;
>			InputTable.cYear+cMonth between lcFirstMonth and lcLastMonth;
>			; && Probably You want the full Quater here but that's easy to change
>			; && This where clause is also added here, because otherwise all months of the
>			; && quater are included
>		Group By cCode, cTown, tmpOrder
>
>	Select cCode, cTown, tmpMonth.cYear, '  ' as cQtr, tmpMonth.cMonth,;
>			Sum(iPrice) as YtdVol, Count(*) as YtdNum,;
>			tmpMonth.cYear+tmpMonth.cMonth as tmpOrder;
>		From tmpMonth, InputTable;
>		Where InputTable.cYear = tmpMonth.cYear and;
>			InputTable.cMonth between '01' and tmpMonth.cMonth;
>		Group By cCode, cTown, tmpOrder
>#Else && All results in one SQL
>	Select cCode, cTown, tmpYear.cYear, '  ' as cQtr, '  ' as cMonth,;
>			Sum(iPrice) as YtdVol, Count(*) as YtdNum,;
>			tmpYear.cYear as tmpOrder;
>		From tmpYear, InputTable;
>		Where InputTable.cYear = tmpYear.cYear and;
>			InputTable.cYear+cMonth between lcFirstMonth and lcLastMonth;
>			; && Probably You want the full Year here but that's easy to change
>			; && This where clause is also added here, because otherwise all months of the
>			; && year are included
>		Group By cCode, cTown, tmpOrder;
>	Union;
>	Select cCode, cTown, tmpQtr.cYear, tmpQtr.cQtr, '  ' as cMonth,;
>			Sum(iPrice) as YtdVol, Count(*) as YtdNum,;
>			tmpQtr.cYear+tmpQtr.cQtr as tmpOrder;
>		From tmpQtr, InputTable;
>		Where InputTable.cYear = tmpQtr.cYear and;
>			InputTable.cQtr between '01' and tmpQtr.cQtr and;
>			InputTable.cYear+cMonth between lcFirstMonth and lcLastMonth;
>			; && Probably You want the full Quater here but that's easy to change
>			; && This where clause is also added here, because otherwise all months of the
>			; && quater are included
>		Group By cCode, cTown, tmpOrder;
>	Union;
>	Select cCode, cTown, tmpMonth.cYear, '  ' as cQtr, tmpMonth.cMonth,;
>			Sum(iPrice) as YtdVol, Count(*) as YtdNum,;
>			tmpMonth.cYear+tmpMonth.cMonth as tmpOrder;
>		From tmpMonth, InputTable;
>		Where InputTable.cYear = tmpMonth.cYear and;
>			InputTable.cMonth between '01' and tmpMonth.cMonth;
>		Group By cCode, cTown, tmpOrder;
>	Order by 1,2,8 && cCode, cTown
>	&& And then first the full year, then the results per month, and then per quater
>#EndIf


>The data used for testing follows below.
>I now used the fox command copy to, so there will be no typos <vbg>
>cCode,cTown,cMonth,cQtr,cYear,iPrice

>'01' 'TNZN' '01' 'Q1' '2000' 10
>'01' 'HOEK' '01' 'Q1' '2000' 10
>'01' 'TNZN' '04' 'Q2' '2000' 40
>'02' 'HOEK' '01' 'Q1' '1999' 1
>'02' 'TNZN' '04' 'Q2' '2000' 40
>'02' 'HOEK' '02' 'Q1' '2000' 22
If it's not broken, fix it until it is.


My Blog
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform