AMO olap Test C# generate tsql and mdx

通过AMO访问online的cube,生成等值的TSql和mdx

自动生成等值的TSQL和MDX进行Cube测试.其中难度比较大的部分是拼接TSQL.

暂时不处理calculations,只除理metrics和Regular Type的dimension Usage.

metric的聚合方法只处理(max,min,sum,count,distinct count)

以下是问题的记录与处理情况.

1.adventureworks示例cube中,会把Date dimension的attributes的表名取成dimtime. 未解决 已经解决此问题

2.如果dimension 表中的attributes引用了其他表的字段,则暂时没有解决这个问题. 解决

使用TableJoin和TableLinks方法来解决这个问题.

Tablelinks方法获取dimensionattributes中使用到的字段所在的表与主表的关系链.

Tablejoin:生成连接的语句.

或许不完善.

3.新问题 如果hierarchy的level的source attribute用的是calculation,那么现在仍然会报错,我应该判断

这个字段是不是计算成员,如果是计算成员,则要去取计算成员的定义.

http://technet.microsoft.com/en-us/library/ms345093.aspx

4.没有考虑dimension attribute的orderby 属性与name column. 未解决(尽快解决 已经解决此问题)

5.问题 自连接的情况 如果dimension usage 当中事实表和维度表是一个表的话,需要给表加别名.

现在只考虑事实表与维度表相同的情况,其他的暂时不考虑.

6.在某些情况下,sum出来的结果会发生溢出,所以需要提前把它转化为bigint.

可以在判断其列的类型为int时自动将其转化成bigint. 未解决

7.遇到父子dimension会形成死循环,或者类似存在回链关系的DSV维度,忽略掉. 解决:第二次出现的时候直接断开.

以下是生成等值TSQL与MDX的运行情况,使用Adventurework示例数据仓库SSAS进行测试,除了提到的第一个问题外,

生成的TSQL均可以运行.

   

界面介绍:填入OLAP CUBE的连接字符串,选择DB,CUBE与dimensions.直接点击生成mdxtsql.

以下贴一些主要的方法(代码)

由于dimension可能引用多个表,所以要把这几个表关联起来,有了以下代码:   

   private string TableJoin(DimensionAttribute da)
        {
            //根据l找到sourcetable
            //然后去匹配tablelinks中的长度 然后再去获取
            string morejoin = "";
            string tablelinks = GetTableLinks(da.Parent);
            if (tablelinks.Split(',').Length<3) return "";
            string TableName = da.KeyColumns[0].Source.ToString().Split('.')[0]+",";
            if (tablelinks.IndexOf(TableName).Equals(0)) return "";
            string strUsedTables = tablelinks.Substring(0, tablelinks.IndexOf(TableName)-1);
            List<string> usedTables = strUsedTables.Split(',').ToList<string>();
            usedTables.Remove("");

            DataSet ds = da.Parent.DataSourceView.Schema;
            for (int i = 0; i < ds.Relations.Count && usedTables.Count > 0; i++)
            {
                string childTable = usedTables[0];
                DataRelation dr = ds.Relations[i];
                if (dr.ChildTable.TableName.Equals(childTable))
                {
                    morejoin = morejoin.Append(" JOIN " 
                         + GetSourceQueryDefinition(da.Parent,dr.ParentTable.TableName.ReplaceFirstUnderLineWithDot())
                        ).AppendNewLine().Append("ON ");
                    for (int j = 0; j < dr.ChildColumns.Length; j++)
                    {
                        morejoin = morejoin.Append(
                            dr.ParentTable.TableName.ReplaceFirstUnderLineWithDot()+"." + dr.ParentColumns[j].ColumnName + " = " +
                            dr.ChildTable.TableName.ReplaceFirstUnderLineWithDot() +"." + dr.ChildColumns[j].ColumnName
                            ).AppendNewLine();
                    }
                    usedTables.RemoveAt(0);
                    i = 0;
                }
            }

            return morejoin;
        }
        private string GetTableLinks(Dimension dim)
        {
            HashSet<string> tables = new HashSet<string>();
            string  MainTable =  "";
            string  tablelinks = string.Empty;
            DataSet ds = dim.DataSourceView.Schema;
            MainTable= dim.KeyAttribute.KeyColumns[0].Source.ToString().Split('.')[0];
            tablelinks = tablelinks.Append(MainTable+",");
            for (int i = 0; i < ds.Relations.Count; i++ )
            {
                DataRelation dr = ds.Relations[i];
                if (dr.ChildTable.TableName.Equals(MainTable))
                {
                    tablelinks = tablelinks.Append(dr.ParentTable.TableName + ",");
                    MainTable = dr.ParentTable.TableName;
                    if (tables.Contains(MainTable))
                        break;
                    else
                        tables.Add(MainTable);
                    i = 0;
                }
            }
            return tablelinks;
        }
View Code
 public DataTable GetMDXSQL(Cube _cube)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("MDX", typeof(String));
            dt.Columns.Add("TSQL",typeof(String));
            string mdx = "";
            string tsql = "";

            StringBuilder sbMeasures = new StringBuilder("{");
            foreach (MeasureGroup mg in _cube.MeasureGroups)
            {
                #region Measure
                foreach (Measure m in mg.Measures)
                {
                    #region Metrics
                    if (m.AggregateFunction.Equals(AggregationFunction.Sum)
                        ||
                        m.AggregateFunction.Equals(AggregationFunction.Count)
                        ||
                        m.AggregateFunction.Equals(AggregationFunction.DistinctCount)
                        ||
                        m.AggregateFunction.Equals(AggregationFunction.Max)
                        ||
                        m.AggregateFunction.Equals(AggregationFunction.Min)
                        )
                    {
                        sbMeasures.Append(m.Name.QuoteName().AppendComma());
                        if (m.AggregateFunction.Equals(AggregationFunction.Sum))
                            sbsql.Append(
                                AggregationFunction.Sum.ToString().AppendLeftParenthesis()
                                + m.Source.ToString().ReplaceFirstUnderLineWithDot()
                                .AppendRightParenthesis()
                                + " AS "
                                + m.Name.QuoteName().AppendComma().AppendNewLine()
                                );
                        if (m.AggregateFunction.Equals(AggregationFunction.Count))
                            sbsql.Append("COUNT(*) AS "
                            + m.Name.QuoteName().AppendComma().AppendNewLine()
                            );
                        if (m.AggregateFunction.Equals(AggregationFunction.DistinctCount))
                            sbsql.Append(
                              "COUNT(Distinct "
                               + m.Source.ToString().ReplaceFirstUnderLineWithDot()
                               .AppendRightParenthesis()
                               + " AS "
                               + m.Name.QuoteName().AppendComma().AppendNewLine()
                               );
                        if (m.AggregateFunction.Equals(AggregationFunction.Max))
                            sbsql.Append(
                               AggregationFunction.Max.ToString().AppendLeftParenthesis()
                               + m.Source.ToString().ReplaceFirstUnderLineWithDot()
                               .AppendRightParenthesis()
                               + " AS "
                               + m.Name.QuoteName().AppendComma().AppendNewLine()
                               );
                        if (m.AggregateFunction.Equals(AggregationFunction.Min))
                            sbsql.Append(
                               AggregationFunction.Min.ToString().AppendLeftParenthesis()
                               + m.Source.ToString().ReplaceFirstUnderLineWithDot()
                               .AppendRightParenthesis()
                               + " AS "
                               + m.Name.QuoteName().AppendComma().AppendNewLine()
                               );
                    #endregion

                        sbMeasures.Remove(sbMeasures.Length - 1, 1);//remove the last coma
                        sbMeasures.Append("}");
                        sbsql.Remove(sbsql.Length - 3, 3);//remove ,


                        HashSet<string> selectedDims = GetSelectedDimensions();
                        #region MeasureGroupDimension
                        foreach (MeasureGroupDimension mgd in mg.Dimensions)
                        {
                            if (!selectedDims.Contains(mgd.Dimension.Name)) continue;

                            string _facttable = string.Empty;
                            string _dimensiontable = string.Empty; 
                            string origindimtable = string.Empty;
                            string _joinby = " ON ";
                            string _groupby = " GROUP BY ";

                            if (!mgd.GetType().Name.Equals("RegularMeasureGroupDimension"))
                                continue;
 
                            foreach (MeasureGroupAttribute mga in ((RegularMeasureGroupDimension)mgd).Attributes)
                            {

                                if (mga.Type != MeasureGroupAttributeType.Granularity) continue;
                                origindimtable = mga.Attribute.KeyColumns[0].Source.ToString().Split('.')[0].ReplaceFirstUnderLineWithDot();
                                
                                _dimensiontable = GetSourceQueryDefinition(mgd.CubeDimension.Dimension, origindimtable);
                                _facttable = GetSourceQueryDefinition(mgd.CubeDimension.Dimension, mga.KeyColumns[0].Source.ToString().Split('.')[0].ReplaceFirstUnderLineWithDot());

                                for (int i = 0; i < mga.KeyColumns.Count; i++)
                                {
                                    _joinby += mga.Attribute.KeyColumns[i].Source.ToString().ReplaceFirstUnderLineWithDot();
                                    _joinby += " = " + mga.KeyColumns[i].Source.ToString().ReplaceFirstUnderLineWithDot().Append(" AND ");
                                }
                                break;
                            }
                            _joinby = _joinby.TrimEnd(" AND ".ToCharArray());

                            #region Hierarchy level
                            foreach (Hierarchy h in mgd.CubeDimension.Dimension.Hierarchies)
                            {
                                foreach (Level l in h.Levels)
                                {
                                    mdx =
                                     string.Format(mdxtemplate, sbMeasures.ToString().TrimEnd(','),
                                     h.Parent.Name.QuoteName().Append(".").Append(h.Name.QuoteName())
                                     .Append(".").Append(l.Name.QuoteName()),
                                    _cube.Name.QuoteName());

                                    foreach (DataItem di in l.SourceAttribute.KeyColumns)
                                    {
                                       // _groupby += di.Source.ToString().ReplaceFirstUnderLineWithDot().AppendComma();
                                        _groupby += GetColumnDefinition(l.Parent.Parent.DataSourceView.Schema,di.Source.ToString());
                                    }
                                    _groupby = _groupby.TrimEnd(',');
                                    //if the _facttable == _dimensiontable then give a alias for dimtable
                                    if (_facttable.Equals(_dimensiontable))
                                    {
                                        _dimensiontable += "2";
                                        _groupby = _groupby.Replace(origindimtable, origindimtable + "2");
                                    }

                                    tsql =
                                        sbsql.ToString()
                                        .AppendNewLine()
                                        .Append(" FROM ")
                                        .Append(_facttable)
                                        .Append(" JOIN ")
                                        .Append(_dimensiontable)
                                        .AppendNewLine()
                                        .Append(_joinby);
                                        //.AppendNewLine();
                                        //.Append(_groupby);

                                    string morejoin = TableJoin(l.SourceAttribute);
                                    tsql = tsql.Append(morejoin);
                                   
                                    tsql = tsql.AppendNewLine().Append(_groupby);
                                    _groupby = " GROUP BY ";
                                    
                                    //Add rows for dt
                                    AddRow(dt, mdx, tsql);
                                    
                                }
                            }

                            #endregion

                            #region Attributes
                            if (mgd.CubeDimension.Dimension.Hierarchies.Count == 0)
                            {
                                foreach (DimensionAttribute da in mgd.CubeDimension.Dimension.Attributes)
                                {
                                    if (da.AttributeHierarchyEnabled == true)
                                    {
                                        mdx = string.Format(mdxtemplate, sbMeasures.ToString().TrimEnd(','),
                                            da.Parent.Name.QuoteName().Append(".").Append(
                                            da.Name.QuoteName())
                                            , _cube.Name.QuoteName());
                                    }
                                    else continue;
                                    foreach (DataItem di in da.KeyColumns)
                                    {
                                      //  _groupby += di.Source.ToString().ReplaceFirstUnderLineWithDot().AppendComma();
                                        _groupby += GetColumnDefinition(da.Parent.DataSourceView.Schema, di.Source.ToString());
                                    }
                                    _groupby = _groupby.TrimEnd(',');
                                    //if the _facttable == _dimensiontable then give a alias for dimtable
                                    if (_facttable.Equals(_dimensiontable))
                                    {
                                        _dimensiontable += "2";
                                        _groupby = _groupby.Replace(origindimtable, origindimtable + "2");
                                    }

                                    tsql=
                                        sbsql.ToString()
                                        .AppendNewLine()
                                        .Append(" FROM ")
                                        .Append(_facttable)
                                        .Append(" JOIN ")
                                        .Append(_dimensiontable)
                                        .AppendNewLine()
                                        .Append(_joinby)
                                        //.AppendNewLine()
                                        //.Append(_groupby)
                                        ;
                                    string morejoin = TableJoin(da);
                                    tsql = tsql.Append(morejoin);

                                    tsql = tsql.AppendNewLine().Append(_groupby);
                                    _groupby = " GROUP BY ";

                                    AddRow(dt, mdx, tsql);
                                }
                            }
                            #endregion

                        }
                        #endregion
                        
                        sbsql = new StringBuilder(" SELECT 
");
                        sbMeasures = new StringBuilder("{");
                    }
                }

                #endregion
            }

            return dt;
        }
View Code

由于dimension的source table经常会含有计算列或者本身是named query 所以有了以下代码:

  public string GetSourceQueryDefinition(Dimension dim,string keycolsrc)
        { 
            //获取dim的dsv 获取
            string rst=keycolsrc;
            DataSet ds = dim.DataSourceView.Schema;
            string tbname = keycolsrc.Replace("dbo.","");
            if(ds.Tables.Contains(tbname))
            {
                if(ds.Tables[tbname].ExtendedProperties.Contains("QueryDefinition"))
                    rst = "("+ds.Tables[tbname].ExtendedProperties["QueryDefinition"].ToString() + ") as "+ tbname;
            }

            return rst;
        }
        public string GetColumnDefinition(DataSet ds, string columndatasource)
        {
            string columnDefinition = "";
            string tableName = columndatasource.Split('.')[0];
            string columnName = columndatasource.Split('.')[1];
            if (ds.Tables.Contains(tableName)
               && ds.Tables[tableName].Columns.Contains(columnName)
               && ds.Tables[tableName].Columns[columnName].ExtendedProperties.Contains("ComputedColumnExpression")
                )
            {
                columnDefinition = "(" + ds.Tables[tableName].Columns[columnName].ExtendedProperties["ComputedColumnExpression"].ToString() +")";
            }
            else
            {
                columnDefinition = columndatasource.ReplaceFirstUnderLineWithDot().AppendComma();
            }
            return columnDefinition;
        }
View Code

   

   

   

   

Looking for a job working at Home about MSBI
原文地址:https://www.cnblogs.com/huaxiaoyao/p/3451634.html