一、引言
在項目中,經(jīng)常會涉及到查詢歷史數(shù)據(jù),通常情況下都是使用查詢歷史的專用組件,或者利用系統(tǒng)函數(shù)GetHisDataEx()以及相關(guān)的函數(shù)進行查詢,但是上述兩種方法都有一定的局限性,現(xiàn)在紫金橋推出一種全新的查詢方法:基于內(nèi)置SQL查詢歷史數(shù)據(jù)的方法。
二、功能實現(xiàn)
1.功能頁面布局
首先,創(chuàng)建一個窗口,窗口中如下圖所示布局。放置兩個“起始時間”控件用來控制查詢歷史數(shù)據(jù)的時間范圍,分別命名為_StartTime、_EndTime;放置一個“文本框”,用來輸入時間間隔,命名為_INTERVAL;放置一個“按鈕”,用來控制查詢腳本;在下面放置一個“自由報表”,用來顯示已經(jīng)查詢出來的歷史數(shù)據(jù),命名為RPT_Data。并在窗口導(dǎo)航樹下選擇:畫面\查詢\內(nèi)置SQL查詢,新建一個查詢命名為ObSql1。

2.腳本實現(xiàn)
所有的腳本均寫在查詢按鈕中,方法比較簡單,首先要在設(shè)置時間范圍與時間間隔,然后在查詢按鈕中選擇所要查詢的數(shù)據(jù)點,并按照設(shè)置的數(shù)據(jù)進行查詢,最后將查詢到的數(shù)據(jù)放置到自由報表中。下面來分析查詢按鈕中的腳本。
ObHost Host1;
ObDataTable& ReturnTable;
string StrPar[];
string StrWhereCmd = ""; //Select查詢時的Where語句
string StrNameCmd = ""; //Select查詢時的Where語句中存放點名的字符串
string StrQuery = ""; //總的查詢語句
string StrTableText = "";
int i,j;
int nTagCount; //所要查詢數(shù)據(jù)點的個數(shù)
int nEveryTagCount; //每一個數(shù)據(jù)點返回歷史數(shù)據(jù)的個數(shù)
int nTableVal = 0;
上述部分為定義的一些臨時變量,方便下面寫程序時使用。
if Host1.TagParSelMulti("",StrPar,-1) then
If語句用來判斷是否在點選擇器中選擇了數(shù)據(jù)點,如果選擇了點,才會執(zhí)行下面的腳本
nTagCount = StrPar.GetCount();
for i = 0 to nTagCount-1 step 1
StrNameCmd = StrNameCmd + "'" + StrPar[i] + "',";
next
StrNameCmd = StrNameCmd + "'" + StrPar[nTagCount-1] + "'";
上述語句是將在點選擇器中選擇的數(shù)據(jù)點按照SQL語句的形式拼接成字符串。
StrWhereCmd = "INTERVAL="+IntToStr(#_INTERVAL.Val*1000,10)+"";
StrWhereCmd = StrWhereCmd + " and DATETIME >= #"+#_StartTime.GetStringDateTime()+"#";
StrWhereCmd = StrWhereCmd + " AND DATETIME< #"+#_EndTime.GetStringDateTime()+"#";
StrWhereCmd = StrWhereCmd + " AND NAME IN ("+StrNameCmd+")";
上述語句是拼寫SQL查詢語句中的Where子句,其中第一句是設(shè)置時間間隔;第二句是設(shè)置查詢的其實時間;第三句是設(shè)置查詢的結(jié)束時間;第四句是設(shè)置所要查詢的歷史數(shù)據(jù)的數(shù)據(jù)點。
StrQuery = "SELECT Name,DATETIME,VALUE FROM HISDATA WHERE "+StrWhereCmd+"";
上述語句是拼寫整體的SQL查詢語句,按照Where字句中的設(shè)置信息,從歷史數(shù)據(jù)庫中查詢歷史數(shù)據(jù),并返回Name,DATETIME,VALUE三個字段的信息,這三個字段分別表示點名,歷史數(shù)據(jù)的時間和歷史數(shù)據(jù)。
#ObSql1.Connect("本地");
#ObSql1.Query(StrQuery,ReturnTable);
上述語句是執(zhí)行SQL查詢,并將查詢到的結(jié)構(gòu)返回到通用數(shù)據(jù)表ReturnTable中。
nEveryTagCount = ReturnTable.GetRowCount()/nTagCount;
#RPT_Data.AddCol(nTagCount-1);
#RPT_Data.AddRow(nEveryTagCount-1);
上述語句是按照查詢返回的數(shù)據(jù)個數(shù)及數(shù)據(jù)點的個數(shù),設(shè)置顯示報表的大小,在報表中增加相應(yīng)的列和行。
for i = 2 to #RPT_Data.RowCount() + 1 step 1
#RPT_Data.SetTxt(i,0,StrPar[i-2]); //設(shè)置表頭,內(nèi)容為點名
for j = 0 to nEveryTagCount step 1
ReturnTable.Get("VALUE",j,StrTableText);
#RPT_Data.SetTxt(i,j+1,StrTableText); //按照數(shù)據(jù)點向報表中放置查詢到的數(shù)據(jù)
if #RPT_Data.Txt(1,j+1) == "" then
ReturnTable.Get("DATETIME",j,nTableVal);
#RPT_Data.SetVal(1,j+1,nTableVal); //向報表中放置歷史數(shù)據(jù)點時間,放置之前要 判斷時間是否已經(jīng)存在
endif
ReturnTable.RemoveRow(0);
next
next
endif
上述語句是將查詢到的結(jié)果放置到顯示報表中。
3.運行效果


三、結(jié)束語
通過該方式增加了查詢歷史數(shù)據(jù)隨意性,且加快了數(shù)據(jù)查詢的速度。同時,查詢到的數(shù)據(jù)可以根據(jù)自身需要進行多種形式的展示,方便數(shù)據(jù)的后期處理。
|