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 阅读(1033) 评论(0)  编辑  收藏 所属分类: 工作日志

只有注册用户登录后才能发表评论。


网站导航: