posts - 18,  comments - 0,  trackbacks - 0
          問題描述:
             由于在SELECT字句常帶有聚合函數(shù),這時(shí)如果是非聚合函數(shù)的表達(dá)式也出現(xiàn)在SELECT子句中,則此非聚合函數(shù)的表達(dá)式必須在GROUP BY中出現(xiàn)。如:查詢 AI_94傳票對照表.省/市代號, 求和(AI_94傳票對照表.金額)  來自 AI_94傳票對照表 條件 AI_94傳票對照表.金額 大于 0 分組 AI_94傳票對照表.省/市代號。
             
          情況說明<目前整理出了常用的幾種場景>:  
            ①在SELECT中的非聚合函數(shù)的字段或表達(dá)式必須在GROUP BY中出現(xiàn)
              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中沒有出現(xiàn)的字段或表達(dá)式可以在GROUP BY中出現(xiàn)
              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中的表達(dá)式如果為一個(gè)字段組成,則此字段如果在GROUP BY中出現(xiàn),那么SELECT對應(yīng)的表達(dá)式可以不在GROUP BY出現(xiàn)
              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中的表達(dá)式如果為多個(gè)字段組成,則SELECT對應(yīng)的表達(dá)式必須在在GROUP BY出現(xiàn)(建議設(shè)置表達(dá)式的字段個(gè)數(shù)標(biāo)識)
              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中的字段/表達(dá)式如果為一個(gè)常量,則一定不能GROUP BY中出現(xiàn)
              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、增加聚合函數(shù)模型對象AggregateFuncModel,繼承普通函數(shù)模型對象FunctionModel
             2、普通函數(shù)setFilter方法修改為protected
             3、修改了語法樹遍歷函數(shù)的代碼,如下:   
           1 
           2 function returns [FunctionModel model]
           3 {
           4     model=null;
           5     ParametersModel p; 
           6     ExpressionModel express1 = new ExpressionModel();
           7 }
           8     :    //Aggregate functions聚合函數(shù)
           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普通函數(shù)
          16     |    f:function_name p=parameters    
          17         {
          18             model = new FunctionModel(f.getText());
          19             model.setParameters(p);
          20         }
          21         
          22         //Normal functions參數(shù)為空的普通函數(shù)[getdate()]
          23     |    #(FUNCTION_EMPTY_PARAM fun1:function_name)
          24         {
          25             model = new FunctionModel(fun1.getText());
          26         }
          27         
          28         //Normal functions參數(shù)為*的普通函數(shù)[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參數(shù)為*的COUNT函數(shù),聚合函數(shù)[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參數(shù)為全部、all的聚合函數(shù)
          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參數(shù)為唯一、distinct的聚合函數(shù)
          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字句中非聚合函數(shù)表達(dá)式卻沒有在GROUP BY出現(xiàn)的表達(dá)式
             5、增加非聚合函數(shù)表達(dá)式對象UnAggregateExpVO,用來對存放單個(gè)字段的非聚合函數(shù)表達(dá)式。
             6、修改了編譯器模型對象QueryModel的parseQuery方法,修改思路如下:       
               ①獲取所有聚合函數(shù)表達(dá)式,存放在aFunMap的Map中,并設(shè)置是否存在標(biāo)識(默認(rèn)為不存在)
               ②獲取SELECT子句的所有表達(dá)式,并與aFunMap的KEY進(jìn)行比較,如果存在,則設(shè)置aFunMap的值為存在標(biāo)識;如果不存在則放入nGroupExprMap的  Map中,如果此表達(dá)式為單個(gè)字段的表達(dá)式,則構(gòu)造UnAggregateExpVO對象并同時(shí)放入mGroupSingleExprMap中。
               ③獲取GROUP BY子句的所有表達(dá)式,并與nGroupExprMap比較,如果存在則設(shè)置為存在標(biāo)識;如果不存在,與mGroupSingleExprMap比較,如果存在則設(shè)置此表達(dá)式標(biāo)識也為存在
               ④遍歷SELECT子句的所有非聚合函數(shù)表達(dá)式,如果其標(biāo)識為不存在,則構(gòu)造NoGroupExistsException并將此表達(dá)式放入異常集合中即可。
            
            代碼如下:
            
              //==== SELECT子句中非聚合函數(shù)表達(dá)式必須在GROUP BY子句中出現(xiàn) BEGIN ====//
              Map aFunMap = new LinkedHashMap();    //聚合函數(shù)Map
              
              
          //獲取所有聚合函數(shù)Model數(shù)組
              QueryModel[] _aggregateFunModelArr = model.getModelsFromAllChildrenByClass(AggregateFuncModel.class);
              
              
          if (_aggregateFunModelArr.length > 0){    //如果存在聚合函數(shù)
                  
          // 循環(huán)獲取所有聚合函數(shù)Model數(shù)組相關(guān)信息
                      for (int i = 0; i < _aggregateFunModelArr.length; i++) {
                          aFunMap.put(_aggregateFunModelArr[i].getChString(), IS_NOT_EXISTS);    
          //將聚合函數(shù)放入Map中,標(biāo)識為IS_NOT_EXISTS
                          
          //QueryModel apm = _aggregateFunModelArr[i].getFirstModelByClass(ParametersModel.class);
                          
          // 得到每個(gè)集合函數(shù)的所有參數(shù)表達(dá)式模型
                          
          //QueryModel expm = apm.getFirstModelByClass(ExpressionModel.class);
                          
          //QueryModel[] expms = apm.getModelByClass(ExpressionModel.class);
                          
          // 得到每個(gè)集合函數(shù)的所有字段模型
                          
          //QueryModel[] fdms = apm.getModelsFromAllChildrenByClass(FieldModel.class);
                      }
                      
                      Map nGroupExprMap 
          = new LinkedHashMap();                //需要在分組出現(xiàn)的表達(dá)式Map
                      Map mGroupSingleExprMap = new LinkedHashMap();    //可分組出現(xiàn)的單個(gè)表達(dá)式Map
                      
          //獲取SELECT子句下的所有表達(dá)式
                      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的表達(dá)式
                          
                          
          if (!((ExpressionModel)expm).hasConstant()){    //如果不是常量則與帶有聚合函數(shù)的表達(dá)式進(jìn)行比較(目前abs(-900)認(rèn)為不是常量)
                              if (aFunMap.containsKey(expm.getChString())){
                                  aFunMap.put(expm.getChString(), IS_EXISTS);                        
          //表示此聚合函數(shù)已在SELECT子句中找到
                              }else{
                                  
          //獲取此表達(dá)式的單個(gè)字段,如果為1個(gè),則放入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需要在分組中出現(xiàn)
                                  }else if (fmArr.length == 0){
                                      QueryModel[] smArr 
          = expm.getModelsFromAllChildrenByClass(StringModel.class);
                                      
          if (smArr.length != 1){    //如果表達(dá)式不存在單個(gè)常量(如: abs(-9000))
                                          nGroupExprMap.put(expm.getChString(), IS_NOT_EXISTS);    //表示此KEY需要在分組中出現(xiàn)
                                      }
                                  }
          else{
                                      nGroupExprMap.put(expm.getChString(), IS_NOT_EXISTS);    
          //表示此KEY需要在分組中出現(xiàn)
                                  }
                              }
                          }
                          
                  }
                      
                      
          //獲取GROUP BY列表模型對象
                  QueryModel _groupByListModel = model.getFirstModelByClass(AggregateExprListModel.class);
                  
          //獲取GROUP BY列表中所有表達(dá)式數(shù)組
                  QueryModel[] _groupByExprModelArr;
                  
          if (_groupByListModel == null){
                      _groupByExprModelArr 
          = new QueryModel[0];
                  }
          else{
                      _groupByExprModelArr 
          = _groupByListModel.getModelByClass(AggregateExprModel.class);
                  }
                  
                  
          //如果GROUP BY列表中的表達(dá)式在SELECT字句的需分組的Map(nGroupExprMap)中存在,則設(shè)置存在標(biāo)識
                  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())){
                          
          //判斷此表達(dá)式的單個(gè)字段是否出現(xiàn),如果在分組中出現(xiàn),則設(shè)置存在標(biāo)識
                          UnAggregateExpVO unAggregateExpVO = (UnAggregateExpVO) mGroupSingleExprMap.get(_groupByExprModelArr[i].getChString());
                          nGroupExprMap.put(unAggregateExpVO.getUnAggregateExp(), IS_EXISTS);
                      }
                  }
                  
                  
          //循環(huán)獲取需分組的Map(nGroupExprMap)中,在GROUP BY沒出現(xiàn)的SELECT表達(dá)式則放入編譯器異常集合中
                  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);
                      }
                  }
                  
                  
          // 得到所有函數(shù)模型(包括一般函數(shù)和聚合函數(shù))--此函數(shù)會(huì)帶有GROUP BY中的函數(shù)
                  
          //QueryModel[] _allFunctionModelArr = model.getModelsFromAllChildrenByClass(FunctionModel.class);
              }
              
          //====SELECT子句中非聚合函數(shù)表達(dá)式必須在GROUP BY子句中出現(xiàn) END ===//

          LORD
          jiandeh@sina.com
          2007-05-22
          posted on 2007-05-22 11:55 LORD BLOG 閱讀(1049) 評論(0)  編輯  收藏 所屬分類: 工作日志
          主站蜘蛛池模板: 和顺县| 从化市| 秦安县| 南漳县| 亳州市| 五家渠市| 丰原市| 许昌市| 汉沽区| 黄平县| 万山特区| 鄢陵县| 三门峡市| 永平县| 务川| 临潭县| 泸水县| 沙洋县| 龙山县| 长岭县| 榆中县| 怀宁县| 迁西县| 泸定县| 启东市| 济阳县| 松原市| 儋州市| 平泉县| 陇川县| 康保县| 武冈市| 甘洛县| 潼关县| 沽源县| 邢台县| 大宁县| 稻城县| 简阳市| 祁东县| 宾阳县|