######### KPI3 해결 과정 ######### 
목표
9.KPI3 
    조회기간 : 1주일-> 1달 로변경
    탭 추가 : 전체,1,2,3,4
    가열로 당 A,B
    A = 실적입열량   -> TB_FUEL_KPI_Model   Date,Fce_No,Gas_Flow
    B = 예측입열량   -> TB_FUEL_KPI         Date,Fce_No,Gas_Flow
    C = A/B 비례개수
    result = C의 표준편차
    기본 계산공식 A,B,C
    A,B 도출 공식:
    0700~1900 오전 Sum(A),Sum(B) ,C = Sum(A)/Sum(B)
    1900~0700 오후 Sum(A),Sum(B) ,C = Sum(A)/Sum(B)
    result = avg(C) 의 표준편차
######### KPI3 해결 과정 ######### 
테이블에 있는 데이터 확인
TB_FUEL_KPI       ->예측
TB_FULE_KPI_MODEL ->실측
테이블 모양(간략화)
DATESTART,DATEEND,GAS_FLOW,FCE_NO 
원하는 데이터
특정 기간내 의 하루를 오전 오후로 나눈 시간의 
    TB_FUEL_KPI_MODEL의 SUM(GAS_FLOW) as GAS_FLOW_A
    TB_FUEL_KPI의 SUM(GAS_FLOW) as GAS_FLOW_B
    값(FCE_NO당)
어려웠던 점
일단 쿼리로 전부 합계까지 구해서 해결하려고 조인이나 여러가지를 써봤는데 중복으로 계산이 되어서 sum값을 찾을수가 없었다
이유는 기준이 되는 데이터가 없다 (DATE가 같지않음)
그래서 여러 컬럼이 1:N이 되어버려서 중복 계산이 되는것
그리고 A,B를 한번에 컬럼으로 뽑아내는 쿼리도...결국 실패하여서
TABLE 이름으로 나누어서 쿼리를 짜서 클라이언트에서 A,B를 구분하기로 함
결국은 오전의 결과 쿼리 + 오후의 결과 쿼리 
select *from(
  SELECT FCE_NO, MIN(DateStart) as startDate, MAX(DateStart) as endDate, SUM(Gas_Flow) as Gas_Flow_A, 'TB_FUEL_KPI_MODEL' as table_name
  FROM TB_FUEL_KPI_MODEL
  where {0} <= DateStart and DateStart< {1}
  GROUP by FCE_NO
  union
  Select FCE_NO, MIN(DateStart) as startDate,MAX(DateStart)as endDate,SUM(Gas_Flow) as Gas_Flow_B,'TB_FUEL_KPI' as table_name
  from TB_FUEL_KPI
  where
{0} <= DateStart and DateStart< {1}
  Group by Fce_No
)AS b
이 쿼리를 하면 결과값은
FCE_NO, startDate,endDate,Gas_Flow,table_name
으로 결과값이 나온다
그러면 클라이언트에서 데이터를 위의 형식으로 모든 날짜에 대하여 받는다
컨버팅 과정은 dictionary와 새로운 데이터클래스를 정의하여서 해결했다.
정의한 데이터 클래스
public class KPI3_Datas
{
    public int fce_no;
    public string startDT;
    public string endDT;
    public double Gas_A; //Tablename 이 TB_FUEL_KPI_MODEL이라면 A
    public double Gas_B; //Tablename이 TB_FUEL_KPI이라면 B
    public KPI3_Datas(int fce_no,string startDT,string endDT,double Gas_A,double Gas_B)
    {
        this.fce_no = fce_no;
        this.startDT = startDT;
        this.endDT = endDT;
        this.Gas_A = Gas_A;
        this.Gas_B = Gas_B;
    }
}
데이터를 한번 for문 쭉 돌리면 결국 A,B를 다 채울수 있다.
결론 :KPI3_Datas의 데이터는 두개의 데이터가 있어야 A,B가 다 찬다.
같은 데이터라는것은 key 값을 
    string key = x.Fce_No + x.endDate.Substring(0,9); //초단위 까지 말고 시단위 까지 같으면 같은걸로 쳐주자
    ///key 값 (enddate)값에 대한 dic가 있다면 비어있는 A,B중 하나를 채워준다.//string key = x.Fce_No + x.endDate.Substring(0, 10); 
        /////초단위 까지 말고 시단위 까지 같으면 같은걸로 쳐주자
    //데이터가 이상한건지 매칭이 잘 안됨 9까지 줄이자
    //20200702070000 => 2020070207 까지 줄이기 8까지 해야하나...
    이런식으로 시간 + fce_no을 해서 데이터를 구분했다.
실제 컨버팅 함수
foreach (var x in currentData._kPI3Items) ///서버에서 받은 데이터를 모두 확인한다.
        {
            //if (x.Fce_No == null)
            ///key 값 (enddate)값에 대한 dic가 있다면 비어있는 A,B중 하나를 채워준다.//string key = x.Fce_No + x.endDate.Substring(0, 10); 
            /////초단위 까지 말고 시단위 까지 같으면 같은걸로 쳐주자//데이터가 이상한건지 매칭이 잘 안됨 9까지 줄이자//20200702070000 => 2020070207 까지 줄이기 8까지 해야하나...
            string key = x.Fce_No + x.endDate.Substring(0,10); //초단위 까지 말고 시단위 까지 같으면 같은걸로 쳐주자\
            if (dic_date.ContainsKey(key))
            {
                //기존데이터라면 부족한 데이터를 채워준다
                if (x.table_name == "TB_FUEL_KPI_MODEL")
                    dic_date[key].Gas_A = x.Gas_Flow;
                else
                    dic_date[key].Gas_B = x.Gas_Flow;
            }
            else
            {
                KPI3_Datas tmp;
                ///새로운 데이터가 들어왔다면 table 이름에 따라 A,B를 채워준다
                switch (x.table_name)
                {
                    case "TB_FUEL_KPI_MODEL":
                        //A 실측값 TB_FULE_KPI_Model
                        tmp = new KPI3_Datas(x.Fce_No, x.startDate, x.endDate, x.Gas_Flow, 0);
                        dic_date.Add(key, tmp);
                        break;
                    case "TB_FUEL_KPI":
                        //B 예측값 TB_FULE_KPI
                        tmp = new KPI3_Datas(x.Fce_No, x.startDate, x.endDate, 0, x.Gas_Flow);
                        dic_date.Add(key, tmp);
                        break;
                }
            }
        }
댓글 없음:
댓글 쓰기