posts - 18,  comments - 0,  trackbacks - 0
          問題描述:
             由于在SELECT字句常帶有聚合函數,這時如果是非聚合函數的表達式也出現在SELECT子句中,則此非聚合函數的表達式必須在GROUP BY中出現。如:查詢 AI_94傳票對照表.省/市代號, 求和(AI_94傳票對照表.金額)  來自 AI_94傳票對照表 條件 AI_94傳票對照表.金額 大于 0 分組 AI_94傳票對照表.省/市代號。
             
          情況說明<目前整理出了常用的幾種場景>:  
            ①在SELECT中的非聚合函數的字段或表達式必須在GROUP BY中出現
              SELECT CORP_MEMBER_CODE AS f1, SUBSTRING(META_SORT_CODE, 1, 4) AS f2, SUM(PRICE) AS f3
              FROM MT_CORP_PRODUCT_PRICE
              GROUP BY CORP_MEMBER_CODE, SUBSTRING(META_SORT_CODE, 1, 4)
            ②在SELECT中沒有出現的字段或表達式可以在GROUP BY中出現
              SELECT CORP_MEMBER_CODE AS f1, SUBSTRING(META_SORT_CODE, 1, 4) AS f2, SUM(PRICE) AS f3
              FROM MT_CORP_PRODUCT_PRICE
              GROUP BY CORP_MEMBER_CODE, SUBSTRING(META_SORT_CODE, 1, 4), PRODUCT_NAME
            ③在SELECT中的表達式如果為一個字段組成,則此字段如果在GROUP BY中出現,那么SELECT對應的表達式可以不在GROUP BY出現
              SELECT CORP_MEMBER_CODE AS f1, SUBSTRING(META_SORT_CODE, 1, 4) AS f2, SUM(PRICE) AS f3
              FROM MT_CORP_PRODUCT_PRICE
              GROUP BY CORP_MEMBER_CODE, META_SORT_CODE
            ④在SELECT中的表達式如果為多個字段組成,則SELECT對應的表達式必須在在GROUP BY出現(建議設置表達式的字段個數標識)
              SELECT CORP_MEMBER_CODE AS f1, SUBSTRING(META_SORT_CODE, 1, 4) AS f2,
                     (PRODUCT_NUMBER1 + PRODUCT_NUMBER2) as f3, SUM(PRICE) AS f4
              FROM MT_CORP_PRODUCT_PRICE
              GROUP BY CORP_MEMBER_CODE, SUBSTRING(META_SORT_CODE, 1, 4), (PRODUCT_NUMBER1 + PRODUCT_NUMBER2)
            ⑤在SELECT中的字段/表達式如果為一個常量,則一定不能GROUP BY中出現
              SELECT CORP_MEMBER_CODE AS f1, SUBSTRING(META_SORT_CODE, 1, 4) AS f2,
                     PRODUCT_NUMBER1 + PRODUCT_NUMBER2 AS f3, SUM(PRICE) AS f4, 888 AS f5
              FROM MT_CORP_PRODUCT_PRICE
              GROUP BY CORP_MEMBER_CODE, META_SORT_CODE, PRODUCT_NUMBER1 + PRODUCT_NUMBER2
          處理過程:
             1、增加聚合函數模型對象AggregateFuncModel,繼承普通函數模型對象FunctionModel
             2、普通函數setFilter方法修改為protected
             3、修改了語法樹遍歷函數的代碼,如下:   
           1 
           2 function returns [FunctionModel model]
           3 {
           4     model=null;
           5     ParametersModel p; 
           6     ExpressionModel express1 = new ExpressionModel();
           7 }
           8     :    //Aggregate functions聚合函數
           9         af:aggregate_func_name p=parameters
          10         {
          11             model = new AggregateFuncModel(af.getText(), AggregateFuncModel.NO_FILTER); 
          12             model.setParameters(p);
          13         }
          14         
          15         //Normal functions普通函數
          16     |    f:function_name p=parameters    
          17         {
          18             model = new FunctionModel(f.getText());
          19             model.setParameters(p);
          20         }
          21         
          22         //Normal functions參數為空的普通函數[getdate()]
          23     |    #(FUNCTION_EMPTY_PARAM fun1:function_name)
          24         {
          25             model = new FunctionModel(fun1.getText());
          26         }
          27         
          28         //Normal functions參數為*的普通函數[now(*)]
          29     |    #(FUNCTION_STAR_PARAM funStar:function_name)
          30         {
          31             model = new FunctionModel(funStar.getText());
          32             express1.addOperator("*");
          33             p = new ParametersModel();
          34             p.addParameter(express1);
          35             model.setParameters(p);
          36         }
          37         
          38         //Aggregate functions參數為*的COUNT函數,聚合函數[count(*)]
          39     |    #(FUNCTION_STAR_COUNT fun2:function_name)
          40         {    
          41             model = new AggregateFuncModel(fun2.getText(), AggregateFuncModel.NO_FILTER);
          42             express1.addOperator("*");
          43             p = new ParametersModel();
          44             p.addParameter(express1);
          45             model.setParameters(p);
          46         }
          47         
          48         //Aggregate functions參數為全部、all的聚合函數
          49     |    #(all:"全部" af11:function_name p=parameters)
          50         {
          51             model = new AggregateFuncModel(af11.getText(), AggregateFuncModel.ALL);
          52             model.setParameters(p);
          53         }
          54     |    #("all" af12:function_name p=parameters)
          55         {
          56             model = new AggregateFuncModel(af12.getText(), AggregateFuncModel.ALL);
          57             model.setParameters(p);
          58         }
          59         
          60         //Aggregate functions參數為唯一、distinct的聚合函數
          61     |    #(dist:"唯一" af21:function_name p=parameters)
          62         {
          63             model = new AggregateFuncModel(af21.getText(), AggregateFuncModel.DISTINCT);
          64             model.setParameters(p);
          65         }
          66     |    #("distinct" af22:function_name p=parameters)
          67         {
          68             model=new AggregateFuncModel(af22.getText(), AggregateFuncModel.DISTINCT);
          69             model.setParameters(p);
          70         }
          71     ;
             4、增加NoGroupExistsException異常類,用來存放SELECT字句中非聚合函數表達式卻沒有在GROUP BY出現的表達式
             5、增加非聚合函數表達式對象UnAggregateExpVO,用來對存放單個字段的非聚合函數表達式。
             6、修改了編譯器模型對象QueryModel的parseQuery方法,修改思路如下:       
               ①獲取所有聚合函數表達式,存放在aFunMap的Map中,并設置是否存在標識(默認為不存在)
               ②獲取SELECT子句的所有表達式,并與aFunMap的KEY進行比較,如果存在,則設置aFunMap的值為存在標識;如果不存在則放入nGroupExprMap的  Map中,如果此表達式為單個字段的表達式,則構造UnAggregateExpVO對象并同時放入mGroupSingleExprMap中。
               ③獲取GROUP BY子句的所有表達式,并與nGroupExprMap比較,如果存在則設置為存在標識;如果不存在,與mGroupSingleExprMap比較,如果存在則設置此表達式標識也為存在
               ④遍歷SELECT子句的所有非聚合函數表達式,如果其標識為不存在,則構造NoGroupExistsException并將此表達式放入異常集合中即可。
            
            代碼如下:
            
              //==== SELECT子句中非聚合函數表達式必須在GROUP BY子句中出現 BEGIN ====//
              Map aFunMap = new LinkedHashMap();    //聚合函數Map
              
              
          //獲取所有聚合函數Model數組
              QueryModel[] _aggregateFunModelArr = model.getModelsFromAllChildrenByClass(AggregateFuncModel.class);
              
              
          if (_aggregateFunModelArr.length > 0){    //如果存在聚合函數
                  
          // 循環獲取所有聚合函數Model數組相關信息
                      for (int i = 0; i < _aggregateFunModelArr.length; i++) {
                          aFunMap.put(_aggregateFunModelArr[i].getChString(), IS_NOT_EXISTS);    
          //將聚合函數放入Map中,標識為IS_NOT_EXISTS
                          
          //QueryModel apm = _aggregateFunModelArr[i].getFirstModelByClass(ParametersModel.class);
                          
          // 得到每個集合函數的所有參數表達式模型
                          
          //QueryModel expm = apm.getFirstModelByClass(ExpressionModel.class);
                          
          //QueryModel[] expms = apm.getModelByClass(ExpressionModel.class);
                          
          // 得到每個集合函數的所有字段模型
                          
          //QueryModel[] fdms = apm.getModelsFromAllChildrenByClass(FieldModel.class);
                      }
                      
                      Map nGroupExprMap 
          = new LinkedHashMap();                //需要在分組出現的表達式Map
                      Map mGroupSingleExprMap = new LinkedHashMap();    //可分組出現的單個表達式Map
                      
          //獲取SELECT子句下的所有表達式
                      QueryModel[] _columnModelArr = model.getModelsFromAllChildrenByClass(ColumnModel.class); 
                      
          for (int i = 0; i < _columnModelArr.length; i++){
                          ColumnModel _columnModel 
          = (ColumnModel) _columnModelArr[i];
                          QueryModel expm 
          =  _columnModel.getFirstModelByClass(ExpressionModel.class);    //獲取ColumnModel的表達式
                          
                          
          if (!((ExpressionModel)expm).hasConstant()){    //如果不是常量則與帶有聚合函數的表達式進行比較(目前abs(-900)認為不是常量)
                              if (aFunMap.containsKey(expm.getChString())){
                                  aFunMap.put(expm.getChString(), IS_EXISTS);                        
          //表示此聚合函數已在SELECT子句中找到
                              }else{
                                  
          //獲取此表達式的單個字段,如果為1個,則放入mGroupSingleExprMap中
                                  QueryModel[] fmArr = expm.getModelsFromAllChildrenByClass(FieldModel.class);
                                  
          if (fmArr.length == 1){
                                      UnAggregateExpVO unAggregateExpVO 
          = new UnAggregateExpVO();
                                      unAggregateExpVO.setUnAggregateExp(expm.getChString());
                                      unAggregateExpVO.setSingleExp(fmArr[
          0].getChString());
                                      unAggregateExpVO.setExistsFlag(IS_NOT_EXISTS);
                                      mGroupSingleExprMap.put(fmArr[
          0].getChString(), unAggregateExpVO);
                                      nGroupExprMap.put(expm.getChString(), IS_NOT_EXISTS);    
          //表示此KEY需要在分組中出現
                                  }else if (fmArr.length == 0){
                                      QueryModel[] smArr 
          = expm.getModelsFromAllChildrenByClass(StringModel.class);
                                      
          if (smArr.length != 1){    //如果表達式不存在單個常量(如: abs(-9000))
                                          nGroupExprMap.put(expm.getChString(), IS_NOT_EXISTS);    //表示此KEY需要在分組中出現
                                      }
                                  }
          else{
                                      nGroupExprMap.put(expm.getChString(), IS_NOT_EXISTS);    
          //表示此KEY需要在分組中出現
                                  }
                              }
                          }
                          
                  }
                      
                      
          //獲取GROUP BY列表模型對象
                  QueryModel _groupByListModel = model.getFirstModelByClass(AggregateExprListModel.class);
                  
          //獲取GROUP BY列表中所有表達式數組
                  QueryModel[] _groupByExprModelArr;
                  
          if (_groupByListModel == null){
                      _groupByExprModelArr 
          = new QueryModel[0];
                  }
          else{
                      _groupByExprModelArr 
          = _groupByListModel.getModelByClass(AggregateExprModel.class);
                  }
                  
                  
          //如果GROUP BY列表中的表達式在SELECT字句的需分組的Map(nGroupExprMap)中存在,則設置存在標識
                  for (int i = 0; i < _groupByExprModelArr.length; i++){
                      
          if (nGroupExprMap.containsKey(_groupByExprModelArr[i].getChString())){
                          nGroupExprMap.put(_groupByExprModelArr[i].getChString(), IS_EXISTS);
                      }
          else if (mGroupSingleExprMap.containsKey(_groupByExprModelArr[i].getChString())){
                          
          //判斷此表達式的單個字段是否出現,如果在分組中出現,則設置存在標識
                          UnAggregateExpVO unAggregateExpVO = (UnAggregateExpVO) mGroupSingleExprMap.get(_groupByExprModelArr[i].getChString());
                          nGroupExprMap.put(unAggregateExpVO.getUnAggregateExp(), IS_EXISTS);
                      }
                  }
                  
                  
          //循環獲取需分組的Map(nGroupExprMap)中,在GROUP BY沒出現的SELECT表達式則放入編譯器異常集合中
                  for (Iterator it = nGroupExprMap.keySet().iterator(); it.hasNext();){
                      String selectExpr 
          = (String) it.next();
                      
          if (((String)nGroupExprMap.get(selectExpr)).equals(IS_NOT_EXISTS)){
                          NoGroupExistsException _exception 
          = new NoGroupExistsException(selectExpr);
                          exs.add(_exception);
                      }
                  }
                  
                  
          // 得到所有函數模型(包括一般函數和聚合函數)--此函數會帶有GROUP BY中的函數
                  
          //QueryModel[] _allFunctionModelArr = model.getModelsFromAllChildrenByClass(FunctionModel.class);
              }
              
          //====SELECT子句中非聚合函數表達式必須在GROUP BY子句中出現 END ===//

          LORD
          jiandeh@sina.com
          2007-05-22
          posted on 2007-05-22 11:55 LORD BLOG 閱讀(1051) 評論(0)  編輯  收藏 所屬分類: 工作日志
          主站蜘蛛池模板: 宜黄县| 永胜县| 台中市| 友谊县| 教育| 绥江县| 温宿县| 泽普县| 资源县| 灌云县| 防城港市| 平远县| 广平县| 镇原县| 平谷区| 元谋县| 鹤岗市| 政和县| 哈尔滨市| 潼南县| 河北区| 安西县| 南宫市| 中西区| 吴川市| 饶河县| 宝清县| 区。| 井陉县| 都安| 顺平县| 策勒县| 株洲县| 旌德县| 静乐县| 长岛县| 清苑县| 柳州市| 德钦县| 马山县| 陇西县|