数据仓库——MDX之查询语句(select..from..where)

lbbb 2000-04-17 10:27:00
数据仓库中要进行olap查询,where的使用方法。
比如要查1997年10月1日-1997年12月15日的数据。
microsoft olap MDX Sample #3:
with member [Measures].[Store Sales Last Period] as '([Measures].[Store Sales], Time.PrevMember)'
select
{[Measures].[Store Sales Last Period]} on columns,
{TopCount([Product].[Product Department].members, 5, [Measures].[Store Sales Last Period])} on rows
from Sales
where ?????????
...全文
225 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
Axiong 2000-05-23
  • 打赏
  • 举报
回复
MDX的条件使用同sql不一样,因为他是Multidimensional的。下面只给你提示一下。

SELECT Measures.MEMBERS ON COLUMNS,
{[Time].[1997]:[1998]} ON ROWS
FROM [Sales]
1. jpivot加入其它应用中 解压jpivot.war 文件,在你的应用当中你需要下面的这些文件: /wcf/** /jpivot/** /WEB-INF/wcf/** /WEB-INF/jpivot/** /WEB-INF/lib/** 最后你还需要对比 jpivot.war 里的 web.xml 文件去修改你自己的 web.xml 文件。 2. 例子说明 一个Schema的xml文件,定义立方体;(feeSchema.xml) 一个jsp文件(fee.jsp),使用jpivot的标签(jp:mondrianQuery),写入多维查询表达式。 2.1. 数据库连接  直接用jdbc  在应用服务器中定义数据源 例子在tomcat中定义了数据源feeDS 2.2. 各种维度类型  一般维度 例子中定义了维度:[term].[所有终端] 按终端id统计缴费情况。  多level维度 例子中定义了维度:[agentTerm].[所有终端] 按代理商,终端两级统计缴费情况  有父子关系维度 例子中定义了维度:[area].[所有地区] 按组织机构级别统计缴费情况 在定义父子级别时,要指定parentColumn和nullParentValue 且要定义Closure,如果不定义,指标钻取的数据有问题。 Closure表针对维度表计算distance,Closure表的生产参见例子中的存储过程sp_zycreateorgclosure 例如: 3. Mondrian Schema详解 3.1. Schema Schema 定义了一个多维数据库。包含了一个逻辑模型,而这个逻辑模型的目的是为了书写 MDX 语言的查询语句。这个逻辑模型实际上提供了这几个概念: Cubes (立方体)、维度( Dimensions )、层次( Hierarchies )、级别( Levels )、和成员( Members )。而一个 schema 文件就是编辑这个 schema 的一个 xml 文件。在这个文件中形成逻辑模型和数据库物理模型的对应。 3.2. Cube 一个 Cube 是一系列维度 (Dimension) 和度量 (Measure) 的集合区域。在 Cube 中, Dimension 和 Measure 的共同地方就是共用一个事实表。 Cube 中的有以下几个属性: 属性名 含义 name Cube 的名字 caption 标题 , 在表示层显示的 cache 是否对 Cube 对应的实表用 mondrian 进行存储 , 默认为 true enabled 是布尔型的 , 如果是被激活 ,Cubes 就执行 , 否则就不予理睬,默认为 true Cube 里面有一个全局的标签定义了所用的事实表的表名 3.3. Dimension 他是一个层次( Hierarchies )的集合 , 维度一般有其相对应的维度表 . 他的组成是由层次( Hierarchies )而层次( Hierarchies )又是有级别( Level )组成 . 其属性如下: 属性名 含义 name Dimension 的名称 type 类型,有两个可选的类型: StandarDimension 和 TimeDimension ,默认为 StandardDimension caption 标题 , 在表示层显示的 UsagePrefix 加前缀 , 消除歧义 foreignKey 外键,对应事实表中的一个列,它通过 元素中的主键属性连接起来。 3.4. Hierarchy 你一定要指定其中的各种关系 , 如果没有指定 , 就默认 Hierarchy 里面装的是来自立方体中的真实表 . 属性如下: 属性名 含义 name Hierarchy 的名称,该值可以为空,为空时表示 Hirearchy 的名字和 Dimension 的名字相同。当一个 Dimension 有多个 Hierarchy 时,注意 name 值要唯一。 hasAll 布尔型的 , 决定是否包含全部的成员 member allMemberName 所有成员的名字 , 也就是总的标题 , 例如: allMemberName= “全部产品” allLevelName 所有级别的名字,它会覆盖其下所有的 Member 的 name 和所有的 Level 的 name 属性的值。 allMemberCaption 例如 : allMemberCaption= “全部产品”这个是在表示层显示的内容 PrimaryKey 通过主键来确定成员,该主键指的是成员表中的主键,该主键同时要与 Dimension 里设置的 foreignKey 属性对应的字段形成外键对应关系 primaryKeyTable 如果成员表不只一个,而是多个表通过 join 关系形成的,那么就要通过这个属性来指明 join 的这些表中,哪一个与 Dimension 里设置的 foreignKey 属性形成外键关系。通过该属性来指明主表 caption 标题 , 在表示层显示的 defaultMember memberReaderClass 设定一个成员读取器,默认情况下 Hierarchy 都是从关系型数据库里读取的,如果你的数据不在 RDBMS 里面的话,你可以通过自定义一个 member reader 来表现一个 Hierarchy 。 3.5. Level 级别 , 他是组成 Hierarchy 的部分。属性很多,并且是 schema 编写的关键,使用它可以构成一个结构树, Level 的先后顺序决定了 Level 在这棵树上的的位置,最顶层的 Level 位于树的第一级,依次类推。 Level 的属性如下: 属性名 含义 name 名称 table 该 Level 要使用的表名 column 用上面指定的表中某一列作为该 Level 的关键字 nameColumn 用来显示的时候使用,如果不定义,那么就采用上面的 column 的值来进行显示。 oridinalColumn 定义该 Level 上的成员的显示顺序,如果不指定,那么采用 column 的值。 parentColumn 在一个有父 - 子关系的 Hierarchy 当中,当前 Level 引用的是其父成员的列名。好比是一张部门表,在一张表里表现部门的上下级关系,一个是主键,肯定还有一个字段为连接到该主键的外键的列名,这里的 parentColumn 指的就是这个列名。 nullParentValue 如果当前的 Level 是有上下级关系(设置了 parentColumn 属性),如果该 Level 又处于顶级,我们需要将顶级的数据取出来,这里指的是位于顶级的父成员的值,有些数据库不支持 null, 那么也可以使用 ’0’ 或 ’-1’ 等,这就表示顶级的成员的父 ID 为 ’0’ 或为 ’-1’ 。 type 数据类型,默认值为 string 。当然还可以是 Numeric 、 Integer 、 Boolean 、 Date 等。 uniqueMembers 该属性用于优化产生的 SQL ,如果你知道这个级别和其父级别交叉后的值或者是维度表中给定的级别所有的值是唯一的,那么就可以设置该值为 true ,否则为 false 。 levelType 该 Level 的类型,默认为 regular (正常的),如果你在其 Dimension 属性 type 里选择了 TimeDimension 那么这里就可以选择 TimeYears 、 TimeQuarters 、 TimeMonth 、 TimeWeeds 、 TimeDays 。 hideMemberIf 在什么时候不隐藏该成员,可选的值有三个: Never 、 IfBlankName 、 IfParentName approxRowCount 该属性可以用来提高性能,可以通过指定一个数值以减少判断级别、层次、维度基数的时间,该属性在通过使用 XMLA 连接 Mondrian 很有用处。 caption 标题 , 在表示层显示的 captionColumn 用来显示标题的列 formatter 该属性定义了 Member.getCaption() 方法返回的动作值,这里需要是一个实现了 mondrian.olap.MemberFormatter 接口的类,用来对 Caption 地值进行格式化。 3.6. Join 对于一个 Hierarchy 来说,有两种方式为其指定:一种是直接通过一个 Table 标签指定;一种是通过 Join 将若干张表连接起来指定。一旦采用 Join 的话,那么就要在 Hierarchy 里的 primaryKeyTable 属性指定主表。 3.7. Measure Measure 就是我们要计算的数值,操作的核心。它的属性如下: 属性名 含义 name 名称 aggregator 要采用的计算函数 column 要计算的列名 formatString 计算结果的显示格式。 visible 是否可见 datatype 数据类型,默认为 Numeric formatter 采用类来对该 Measure 的值进行格式,具体参考 Level 的 formatter 属性。 caption 标题,用来显示时使用。 4. JPivot标签库使用详解 4.1. Introduce JPivot 是一套基于 Mondrian 的 OLAP 前端展现工具,它提供了一套标签库来解决的 OLAP 的展现层问题。 在一个 JSP 页面当中,如果要使用 JPivot 标签库,除了要配置相关的配置文件外,我们需要在 JSP 头的位置声明对 JPivot 标签库的引用,引用方法如下: <%@ taglib uri = "http://www.tonbeller.com/jpivot" prefix = "jp" %> JPivot 标签库包含以下几个标签: chart chooseQuery clickable destroyQuery mondrianQuery navitator print scalarQuery setParam table testQuery xmlaQuery 接下来我们将详细介绍这些标签的具体用法及相关参数的含义。 4.2. chart 创建一个图表组件,这个图表组件的标签不能直接产生可见输出,它必须通过 WCF 的渲染标签才行。 chart 标签的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 id 是 String 是 标签的 ID visible 否 boolean 是 用来设置该组件是否可见,当该属性为 false 时 WCF 标签半角不显示该组件。 role 否 String 是 Role 的名称,如: role=”tomcat” 就允许当前用户角色为 tomcat 的访问该控件, role=”!tomcat” 则就允许除角色为 tomcat 以外的所有的用户访问。 query 是 OlapModel 是 一个 mondrianQuery 标签的 ID 值 baseDisplayURL 否 String 是 显示图表的链接,链接的后面还要添加参数“ ?=filename=[ 临时图表文件的名称 ] ” controllerURL 否 String 是 链接到 JPivot Controller 的 URL ,该属性在一些复杂环境下比如 Portal 之类就很有用。 4.3. chooseQuery 从前面创建的若干个查询当中选择一个合适的查询(通过查询名称进行选择),例如: SELECT ... SELECT ... ... 它的属性比较简单,只有 id 和 queryName 两个,而且比较容易理解。 4.4. clickable 该标签的作用是给一个 dimension 或一个 level 里的所有的 members 加上超链,使得它们变的可以进行点击操作。生成的 URL 中包含这个 member 的唯一名称,这个标签必须要在一个 table 或一个 query 的标签里嵌套使用。 这个动作还依赖于该标签的 sessionParam 属性,如果该属性存在,那么参数值将在页面显示之前写到 com.tonbeller.jpivot.param.SessionParamPool 当中,如果不存在该属性,参数将会被编码到超链接当中。 例如: select .. from Sales 该标签的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 urlPattern 否 String 是 该属性已过时,使用 page 属性替代它。 page 否 String 是 目标页面的名称,该属性的值必须要以“ / ”开始,如果不设置,那么会采用当前页面的名称。 uniqueName 否 String 是 一个 dimension 或 hierarchy 或 level 的唯一名称,用来标识哪个 member 将可以点击。 menuLabel 否 String 是 如果多次定义 clickable ,那么它将通过一个右键来进行显示,这里的值就是右键菜单的名称。 sessionParam 否 String 是 参数名称,它将会被回写到 com.tonbeller.jpivot.param.SessionParamPool 当中。 propertyName 否 String 是 该属性如果存在,该 member 属性的值将会被带到 com.tonbeller.jpivot.param.Parameter 的 sqlValue 的属性当中。 propertyPrefix 否 String 是 如果存在该属性,多个 SessionParam 将会被创建,每一个 member 的名字的开始部分将采用该属性的值。 providerClass 否 String 是 如果存在该属性,这个类的实例将会从当前的 member 中获取 SessionParam 对象的实例,这里的类必须实现 com.tonbeller.jpivot.table.navi.ClickableMember.ParameterProvider 接口。 4.5. destroyQuery 该标签的主要作用是销毁所有的查询,它的用法如下: 它只有一个 ID 属性。 4.6. mondrianQuery 该标签的主要作用是让 mondrian 执行指定的查询,该标签需要指定一个 JDBC 的 datasource 或单独指定 JDBC 连接的各个属性从而可以让 mondrian 连接到指定的数据库。 它的用法如下: select {[Measures].[Unit Sales], [Measures].[Store Cost], [Measures].[Store Sales]} on columns, {[Product].[All Products]} ON rows from Sales where ([Time].[1997]) 它的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 id 是 String 是 标签的 ID jdbcDriver 否 String 是 要连接到目标数据库的驱动类名 jdbcUrl 否 String 是 目标数据库的 URL jdbcUser 否 String 是 登录数据库的用户名 jdbcPassword 否 String 是 登录数据库的密码 dataSource 否 String 是 可以连接到数据库的 JNDI 名称,如 jdbc/SampleDB ,当使用它时另外四个单独连接数据库的属性不可以再用。 catalogUri 是 String 是 Mondrian Schema 文件所在的路径,指定路径时需要从 web 应用的根开始,如 /WEB-INF/FoodMart.xml 。 role 否 String 是 指定角色,该角色的值来自 Mondrian Schema 里定义的角色。 dynResolver 否 String 是 指定一个用来解析 Mondrian Schema 里定义的动态变量的解析类。 connectionPooling 否 String 是 当该值为 false 时,将从连接池里阻止 Mondrian dynLocale 否 String 是 设置动态解析 Mondrian Schema 里的 Local dataSourceChangeListener 否 String 是 指定一个类用来检测 datasource 的变化。 queryName 否 String 是 这个属性允许保留多个查询,对于每一个查询,最后一个查询将会被存储下来,可以使用 chooseQuery 标签在查询间进行切换。 stackMode 否 boolean 是 如果设置为 false ,那么所有的查询将同时被处理;如果设置为 true ,那么将保持其原有的顺序,例如: 查询名称为 qn1 的创建后,标签就马上将其显示出来 ; 接下来创建 qn2 ,现在 stack 里有 qn1 和 qn2 , qn2 也将被显示出来。 4.7. navigator 创建一个导航组件,这个组件不会直接输出,它必须通过 WCF 的标签来 render 输出。 示例用法: 该标签的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 id 是 String 是 标签的 ID query 是 OlapModel 是 指定一个 mondrianQuery 标签的名称 visible 否 boolean 是 设置该组件是否可见,如果设置为 false 那么 WCF 的 render 标签将不会 render 该组件。 role 否 String 是 角色的名称,可以加前缀“!”,表示“除 … 角色之外”都可以访问该组件,否则就是只有该角色才能访问该组件。 4.8. print 创建一个打印控件,该控件不能直接输出,你必须创建 WCF form 来调用打印的 servlet 来生成 XLS/PDF 文件。 该标签只有一个 ID 属性。 4.9. scalarQuery 创建一个包含由单个单元格的组成的 OLAP 结果的会话属性,它的值由标签的属性提供。 示例用法: formattedValue="#{some.bean.otherProperty}" caption="Some Caption" /> 它的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 id 是 String 是 标签的 ID value 是 String 是 是一个 EL 的表达式,通过 EL 表达式来计算值,这里是一个数字。 formattedValue 否 String 是 用一个 EL 表达式来计算格式化后的值,是一个字符串 caption 否 String 是 用一个 EL 表达式来生成 caption 的值,这里是一个字符串 queryName 否 String 是 请参考 mondrianQuery 标签 stackMode 否 boolean 是 请参考 mondrianQuery 标签 4.10. selectProperties 创建一个选择属性的组件,该组件不会直接输出,必须要与 WCF 的 render 标签结合。 示例用法: selectproperties id="selectprop01" table="#{table01}" visible="false"/> 它的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 id 是 String 是 标签的 ID table 是 TableComponent 是 该属性用来指定一个表格组件。 visible 否 boolean 是 设置该组件是否可见,如果设置为 false 那么 WCF 组件将不会显示该组件。 role 否 String 是 指定角色,同样可以使用“!” 4.11. setParam 通过 get 或 post 或 session 里的值为 MDX 查询设置查询参数。示例用法: SELECT ... Parameter("Param01", ... WHERE ... mdxParam="Param01"/> or mdxParam="Param01"/> 它的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 query 是 OlapModel 是 指定一个 mondrianQuery 标签的名称 httpParam 否 String 是 http 参数的名称,如果存在该属性,那么它的值将会被告解析并设置到 mdx 查询的 parameter 当中 sessionParam 否 String 是 Session 的参数名称 mdxParam 是 String 是 MDX 的 parameter 的名称 4.12. table 创建一个 pivot 的表格组件,该组件要借助于 WCF 的 render 标签输出。 示例用法: 该标签的主要属性如下: 属性名 必须 数据类型 是否能动态计算指定 描述 id 是 String 是 标签的 ID visible 否 boolean 是 设置组件是否可见,如果为 false 那么 WCF 的标签将不会将其 render 。 role 否 String 是 可访问该组件的角度,支持“!”用法 query 是 OlapModel 是 指定一个 mondrianQuery 标签的名称 5. 多维查询表达式 5.1. 什么是 MDX MDX 的全称是 Mutil Dimensional Expressions ,是由 Microsoft , Hyperion 等公司研究多维查询表达式,是所有 OLAP 高级分析所采用的核心查询语言。 MDX 可以用来进行以下操作: 1. calculated members (计算成员) 2. Calculated Cells (计算单元) 3. Security Settion (安全设置) 4. Custom member formula ( 自定义函数 ) 5. Custom level rollup () 6. Actions (动作) 7. Named “ sets ” ( 命名集合 ) 8. Server side formatting (服务器数据格式化) 5.2. MDX 的基本结构 MDX 的基本结构有三种: Members 、 Tuple 、 Set 。 5.2.1. Members 指的是维度树上的一个节点,这里有一点需要指出,量度也是一个特殊的维度,所以对于普通维度上的 Member 可以有几下几种表示方法: [Customer] 或 [Time].[1996] 等,对于特殊的维度——量度而言,也可以表示一个 Member ,如: [Measures].[ unit sales] 等。 Member 的表示方法就是用中括号的形式,“ [……] ”。 5.2.2. Tuple Tuple :是由若干个 Members 组成,每一个维度上最多只能有一个 Member ,对于一个 Tuple 而言至少有一个维度,多则不限,同时对于没有列出来的那就表示为默认的 Member 。 Tuple 的表示方法是小括号“ () ”,因为其又有 Member 构成,所以通常的格式为“ ([…],[…][…],…) ”;示例: a) ([Regin ].[USA]) b) ([product].[ computers],[time].[2008]) 。 5.2.3. Sets 同一维度上若干个 Members 的集合,或者是若干个 Tuples 的集合,但这里有一个地方需要注意,那就是如果是若干个 Tuple 组成的集合是,各个 Tuple 里的 Member 之间存在着一定的对应关系。集合的表示方法用大括号“ {} ”,所以可能的表示方法为: a) {[time].[2008],[time].[2009],[time].[2000]} ,这里 Set 是由同一维度的若干个 Member 组成。 b) {([computer],[usa ]),([ mobile],[china])} ,这个 Set 是由两个 Tuples 组成,这里大家可以看到,在第一个 Tuple 当中,第一个 Member 是名为 computer 的产品,所以后面的 Tuple 的第一个 Member 也必须是一个产品,所以我们这里看到的是 mobile ,第一个 Tuple 里第二个 Member 是一个国家,所以第二个 Tuple 的第二个 Member 也必须是一个国家名,依次类推。 5.3. MDX 查询语句 一个标准的 MDX 查询语句就是由我们前面介绍的 MDX 的三个基本对象构成,也就是 Member 、 Tuple 、 Set 。 一个标准的 MDX 查询的语法如下: SELECT Set ON COLUMNS, Set ON ROWS FROM Cube WHERE Tuple 示例: SELECT {[time].[ 1997],[time].[1998]} ON COLUMNS, {([product].[drink],[customer].[gender].[F]),( [product].[food],[customer].[gender].[M])} ON ROWS FROM [Sales] WHERE ([Measures].[ StoreSales ]) 这个 MDX 查询就表示:查询时间为 1997 和 1998 两年的 drink 类产品,女消费者和 food 类产品男消费者的 Store Sales 。 5.4. MDX 表达式 5.4.1. children 它的作用是列出指定分类下的所有项,如 1. [product type].[food].children ,这就表示列出产品类型为 food 的所有产品。 2. [region ].[country].children ,这就表示列出所有的国家名称。 该函数不能用在 Tuple 中 5.4.2. CurrentMember 当前某个 Member ,举例: 某个产品销售额贡献度计算,对于某一个产品或一种类型的产品而言它的销售额贡献度指的是它的销售额与所有产品销售额的比值,此时,如果我们要用 MDX 来计算这个贡献度的值是可以采用 CurrentMember 来实现,如: 此时我们的 MDX 表达可以是: ([product].currentMember ,[ Measures].[stores sales]) / ([product].[ all products],[Measures].[stores sales]) 同时因为默认情况下指的就是 currentMember ,所以上面的 currentMember 可以去掉: ([Measures].[ stores sales]) / ([product].[ all products],[Measures].[stores sales]) 所有 MDX 表达式的写法是由若干个 Tuple 组成 ,比如上面的这个表达式就是由两个 Tuple 的相除构成。 5.4.3. prevMember 和 nextMember 这两个元素分别指的是当前 Member 的上一个 Member 和当前 Member 的下一个 Member 。 利用这两个元素我们可以来实现实际当中常见的同期比(前期比),所谓的同期比指的 是: (当前 member- 当前 member 的前一个 member ) / 当前 member 的前一个 member 对应到 MDX 表达式我们可以用 prevMember 和 nextMember 来实现,如: (([time].currentMember ,[ Measures].[store sales])-([time].prevMember ,[Measures].[storessales ])) / ([time].prevMember ,[ Measures].[store sales]) 当然因为 currentMember 可以省略,所以上面的写法也可以是: (([ Measures ].[store sales])-([time].prevMember ,[Measures].[storessales ])) / ([time].prevMember ,[ Measures].[store sales]) 5.4.4. Parents 、 FirstChild 、 Descendants 下面的这张图就显示一个树 这张图中 all 这个节点是 97 和 98 的 parents , 97 和 98 也是 all 的 children ,同时 97 是 all 的 firstChild 如果我们要取到 97 下的所有的月份,那么我们就需要用 Descendants 来实现,它的语法是: Descendants( [time].[97],month) ,这里的 month 是一个 level 的名称。所有它的格式为: Descendants([ 一个 Member], 一个 level 的名称 ) 比如在食品销售当中,我们要知道哪一类的食品更受消费者欢迎,这样我们需要只知道各类食品的销量,比如食物( food )、饮料 (drink) 等的具体销量 (unit sales) ,然后再计算出所有食品总的销量( total sales ) , 如果采用 MDX 我们可以很容易的实现,采用 MDX 后的计算哪种食品更受欢迎的表达式如下: ([food].currentMember ,[ Measures].[unit sales]) / ([food].currentMember.parent ,[ Measures].[total sales]) 因为 currentMember 可以省略,所以上面的写法又可以是: ( [ Measures].[unit sales]) / ([food].currentMember.parent ,[ Measures].[total sales]) 5.5. 参见MDX的基本语法及概念.pdf 6. 常见问题 6.1. MDX编辑器中文乱码  web.xml中添加过滤器 Set Character Encoding com.tonbeller.wcf.charset.CharsetFilter encoding UTF-8 Set Character Encoding /* 注意,该filter-mapping放在所有filter-mapping的最前面  jsp页面编码用UTF-8(testpage.jsp) 6.2. pdf中文显示“#” 1).在WEB-INF\jpivot\print目录下建立userconfig.xml文件。内容如下:(仅配置黑体,fontBaseDir属性我也没有配置,源码中有) 2). 下载Apache的FOP包,应用所需JAR包,生成simhei.xml。Java命令行为: java -cp D:\op\fop.jar;D:\op\avalon-framework-4 .2.0.jar;D:\op\commons-logging-1.0.4.jar;D:\op\commons-io-1.1.jar;D:\op\xmlgraph ics-commons-1.4.jar org.apache.fop.fonts.apps.TTFReader C:\WINDOWS\Fonts\simhei. ttf simhei.xml 3). 将simhei.xml,以及simhei.ttf文件放到WEB-INF\jpivot\print目录下。 4 ). 修改WEB-INF\jpivot\table目录下的fo_mdxtable.xsl文件,把所有的font-family对应成SimHei,(以SimHei开头)。 6.3. pdf格式修改(原格式行太宽) 修改jpivot\WebRoot\WEB-INF\jpivot\table\fo_mdxtable.xsl 中font-size,line-height,padding 6.4. 钻取数据的格式化 在利用jpivot钻取的时候,发现出来的数字数据都精确到了小数点后两位,我可不想所有数字都这么精确,连带出来的id值也被这样格式化了,悲惨! 我的解决方法:取消格式定义 找到wcf.jar,修改com.tonbeller.wfc.format.config.xml 删除double和nandouble的定义 6.5. mondrian 的志的配置 将log4j.xml放置到web-inf/classes下 文件内容如下: 6.6. schema workbench schema的编辑器,界面化编辑schema。 但不知道为什么,在我的本机上,在打开,新建schema文件,都非常慢。 可以到http://sourceforge.net/projects/mondrian/files/下载,最新版本psw-ce-3.2.1.13885 7. 参考资料 http://mondrian.pentaho.com/documentation/ mondrian的官方网站 http://jacky6024.javaeye.com/ 比较有用的中文资料
SQL Server 2005全文检索技术在网站上的应用实录 http://tech.ddvip.com 2008年01月21日 社区交流 Excel服务器-用Excel做管理系统 关键字: DataGuard checkpoint 动态查询 synonyms 卸载SQL 2005 SQL Server群集 内容摘要:本文提供了网站如何设计和实现基于SQL Server 2005的全文检索实例,希望能对正在使用SQL Server 2005构建网站搜索的同仁有所裨益。 一、前言 “人类失去搜索,世界将会怎样?”,同样,很难想象一个拥有极大信息量的行业网站门户没有站内全文搜索将会出现怎样的局面,网站全文检索对于挖掘网站信息和整合网站资源的价值是不言而喻的。我们看到,通用型的搜索引擎已经成为了互联网世界的门户,而对于一个信息量极其丰富的网站而言,全网搜索或许会成为本网站的门户,正是所谓的门户之门。   实现网站全文检索有几种常见方案,比如应用数据库全文检索,开源搜索引擎,使用Google API等, 本文我们将就如何使用SQL Server 2005多快好省地建立网站全文检索展开探讨。 二、全文检索技术说明   1、应用背景   先介绍下Z网站,它是国内投融资行业最大的行业门户,网站拥有海量的融资信息、投资信息、招商信息、创业信息、商机信息、资讯信息、产权交易信息、招标投标信息、中标信息、会展信息等投融资行业的信息资源。网站全文检索实现的首要需求就在于能够让用户输入诸如行业关键字后系统能快速返回给符合用户在全范围内查找条件的记录, 从而有效地利用资源,更好地满足用户需求。 2、主要检索技术的区别   有了数据但是没有被使用,那么这些数据不应该被称为信息。它们无非是不断充斥设备和网络的比特而已,但是如何把数据挖掘出来提供给需要的人员,检索技术是其中非常有效的途径之一。   现基于微软平台,针对SQL Server 2005提供的全文检索技术进行介绍。与关系数据查询、多维数据库查询和基于XML的XQuery、XPath不同,全文检索技术主要处理对象是基于超大 数据量的文本数据和结构化的二进制数据上类似LIKE的模糊查询。主要区别见下表。    表1:全文检索与关系数据库查询、多维数据查询、XML查询的对比      关系数据库查询 多维数据查询 XML查询 全文检索 检索技术 SQL MDX XQuery、XPath SQL (extension) 主要处理对象 关系二维数据 结构化多维数据 层次型数据 大容量二维和层次型数据的模糊检索 主要应用领域 一般的OLTP类应用 一般的OLAP类分析型应用 面向Internet、Intranet的松散耦合SOA应用 企业/网站内部信息/知识管理类应用 索引 大量使用非聚簇索引,一般保存在数据库中。 通过层次型、保存中间结果的方式,通过不同的轴向快速定位信息剖面。 基于XPath的索引,索引一般保存在数据库中。 基于关键字的索引,保存在文件系统中。每个表仅支持一个索引。   3、全文检索技术简要介绍   全文检索主要应用领域如下:   (1)大数据量、超大数据量的结构化平文本数据和模糊匹配查找(Char、Varchar、Nvarchar)。   (2)大数据量、超大数据量的层次型XML数据展开后的查找---含模糊查找(Xml type)。   (3)标准格式的二进制非结构化Word数据的查找(VarBinary[max]、Image)。   与其他检索技术不同的是,全文检索不仅仅提供词汇层次的查询支持,而且可以根据语言环境、不同语言的特点,甚至于用户自定义的配置提供不同语义级的大容量的数据模糊匹配检索支持。为了提供语义层次的检索,SQL Server 2005的全文检索明确了如下几个概念:   (1)断字符(Word Breaker):因为对于不同的语言,哪些符号可以用于词汇的分割是不同的,因此全文检索支持不同语言环境的不同断字符。   (2)标记(Token):是由断字符标识的词或字符串。由于划分是基于特定语言完成的,因此也可以做到语义层次的支持。   (3)干扰词(Noise Word):主要是那些经常出现,但是对于检索没有多少帮助的词汇。例如:英语中的“a”、 “and”、 “is”、 “the”,汉语中的“的”、 “不”、 “以”、 “了”等。SQL Server 2005中提供配置文件,允许用户自定义自己语言、甚至与本行业、本企业的检索干扰词。   (4)词干分析器(Stemmer):通过断字符分割后,根据具体的语言和该语言的语法规程生成的特定词汇的变形。 这个即是搜索引擎常提到的分词技术。   (5)同义词:即便是同一个语言,在检索的情况下也存在同义词如何处理的问题。如果一个检索系统不能够识别近义词,而只能识别完全匹配的词汇,那对于我们中文这种表义的语言而言会带来很大不便。同样的,一个行业内部也有很多同义词或者是缩略语。例如如下的词语。   广播行业:“ABC”与“英国ABC广播公司”基本上类似,但是也可能和“澳大利亚广播公司”混淆。   政府行文:“ABC”与南美的“阿根廷、巴西、智利三国”是同义词。   不仅如此,由于日常使用的习惯,我们在口语表达和书面语表达上也有区别,这个也需要预先定义。例如,很多口头常用的技术产品“Win2K”、 “WinXP”等,一般都很正式的称为“Windows 2000”和 “Windows XP”,因此SQL Server 2005上也提供类似词汇替换的支持,而且这些支持也是与具体语言相关的。   4、SQL Server 2005全文检索的技术架构   让我们首先得问自己,什么是全文检索?它是指Microsoft SQL Server 2005 具备针对 Microsoft SQL Server 表中基于纯字符的数据进行全文查询的功能。全文查询可以包括词和短语,或者词或短语的多种形式。   当我们明确了全文检索概念之后,我们来看看它的内部结构。   Microsoft SQL Server 2005 中的全文搜索由 Microsoft Full-Text Engine for SQL Server (MSFTESQL) 服务提供支持。MSFTESQL 服务有两个角色,即索引支持和查询支持。   全文搜索的组件   全文搜索的体系结构由下列组件构成:   ◆Microsoft Full-Text Engine for SQL Server (MSFTESQL) ◆Microsoft Full-Text Engine Filter Daemon (MSFTEFD),它包含下列组件: (1)筛选器 (2)协议处理程序 (3)断字符   SQL Server中的全文搜索的体系结构如下所示。    图1   让我们逐一介绍两类重要的引擎及其在整个体系结构中的重要作用。   Full-Text Engine for SQL Server (MSFTESQL)   MSFTESQL 服务负责进行下列操作:   ◆填充全文索引。 ◆管理全文索引和全文目录。 ◆帮助对 SQL Server 数据库中的表进行全文搜索。   让我们来看看SQL Server 2005全文索引的过程   全文填充(也称为爬网或爬虫)开始后,数据库引擎会将大批数据存入内存并通知 Microsoft SQL Server 全文引擎 (MSFTESQL) 服务开始进行索引。MSFTESQL 服务将对表的某一列或几列中的字符和格式化二进制数据编制索引。全文引擎将使用协议处理程序组件从内存中取出数据并进行进一步处理,从而生成全文索引。   对存储在 varbinary(max) 或 image 列中的数据编制索引时,筛选器(实现了 IFilter 接口)将基于为该数据指定的文件格式(例如,Microsoft Word)来提取文本。在某些情况下,筛选器组件会要求将 varbinary(max) 或 image 数据写到服务帐户 Temp 目录中,而不是将其存入内存。   在处理过程中,通过断字符将收集到的文本数据分隔成各个单独的标记或关键字。用于标记化的语言将在列级指定,或者也可以通过筛选器组件在 varbinary(max)、image 或 xml 数据内标识。   还可能执行其他处理以删除干扰词并在将标记存储到全文索引或索引片断中之前将这些标记规范化。   Microsoft Full-Text Engine for SQL Server 的功能   SQL Server 2005 为全文引擎提供了并行安装方式。这意味着对于每个 SQL Server 实例,都存在一个专用的 MSFTESQL 实例,其中包括专用的组件(例如断字符和筛选器)、资源(例如内存)和配置(例如服务级设置,实例级的 resource_usage 是一个更具体的例子)。单个 MSFTESQL 服务实例可管理相关联的 SQL Server 实例的全文索引。利用 MSFESQL 服务,SQL Server 可超出 SQL 标准对字符串列执行更为复杂的搜索。   MSFTESQL 服务担当了以下角色:   索引支持   MSFTESQL 实现了为数据库定义的全文目录和索引。   查询支持   MSFTESQL 可处理全文搜索查询并确定索引中符合全文选择条件的项。对于符合选择条件的每一项,MSFTESQL 将向 SQL Server 服务返回相应行的标识外加一个排名值,而后者将使用这些信息来构造查询结果集。所支持的查询类型包括:   ◆搜索词或短语。 ◆搜索位置邻近的词。 ◆搜索词的变形。   可管理性支持   全文目录和索引不会存储在 SQL Server 数据库中。MSFTESQL 服务负责管理全文目录。   Microsoft Full-Text Engine Filter Daemon   MSFTEFD 由负责从表中访问和筛选数据以及进行断字和词干分析的组件组成。   ◆筛选器   筛选器的任务是从文档中提取文本化信息流,并舍弃所有非文本化信息和格式化信息。筛选器将生成文本字符串和属性/值对,并依次将它们传递给索引引擎。   筛选器可从特定的文档格式(如 Microsoft Word 文档或文本文件)中提取文本化信息。例如,Microsoft 提供了 Microsoft Office 筛选器,此筛选器可以从 Word、Microsoft Excel 和 Microsoft PowerPoint 文件中提取文本和属性。其他筛选器用于处理 HTML 或电子邮件。还可以使用第三方筛选器。   ◆SQL 协议处理程序   在 SQL Server 2005 中,SQL 协议处理程序的工作是从指定数据库中的表内访问数据。   断字符   断字符是用于在查询或抓取的文档中确定字符流中的字符边界位置。有关详细信息。   全文搜索的索引组件负责全文索引的初始填充,以及当全文索引表中的数据被修改时该索引的后续更新。为了提升全文索引过程的效率,Microsoft SQL Server 2005 改进了全文收集机制的体系结构,从而大大增强了性能。 Microsoft Full-Text Engine for SQL Server (MSFTESQL) 服务是一个全文索引和搜索引擎。MSFTESQL 引擎基于 Microsoft Search (MSSearch) 技术,它与 Microsoft SQL Server 2005 Database Engine 进行了最为紧密的集成。   全文引擎作为 MSFTESQL 服务在操作系统上运行。SQL Server 与 MSFTESQL 必须拥有相同的服务帐户。默认情况下将安装 MSFTESQL 服务,但是只有在使用全文搜索时才会运行此项服务。   三、网站全文检索设计   1、架构设计 采用OLTP交易数据库和OLAP数据仓库(用于搜索和分析)分离的模式,OLTP作为OLAP的数据源通过SQL Server Integration Services (SSIS)定期导入到OLAP数据仓库环境中,OLAP采用星型结构以便于更好地满足搜索和将来的数据挖掘。 OLAP数据仓库的建立目标为了检索和数据挖掘,故其事实表的建立可以反范式原则设计。    图2   2、原型设计(由于篇幅限制,这里仅给出搜索主页和主要资源查询页面)    图3   3、数据库设计    图4   4、数据字典   MainInfoTab(信息主表)      CapitalInfoTab(资本信息明细表)      ProjectInfoTab(项目信息明细表)      MerchantInfoTab(政府招商信息明细表)      四、数据库全文检索实现   至此,我们已经完成了全文检索的设计工作,现在可以来实现它的功能啦!   首先, 让我们建立检索表的全文检索,全文检索要求唯一索引,故需要在相关表建立唯一聚集索引。   第二步,使用SQL DDL或者SQL Server Management Studio建立表的全文检索。   1)使数据库支持全文检索。    图5   或者通过键入命令 EXEC SP_FULLTEXT_DATABASE 'Enable' 命令达到同样效果。   2)定义表的全文检索目录和索引字段。   在表的鼠标右键通过点击“全文检索定义全文检索”将弹出如下执行向导,本向导执行完毕则该表的全文检索业已完毕。   a)选择要索引的字段    图6   或者键入如下命令:    CREATE FULLTEXT INDEX ON TableName KEY INDEX PK_IndexName ON DB WITH CHANGE_TRACKING AUTO ALTER FULLTEXT INDEX ON TableName ADD ColumnName   b)选择或创建新的索引目录。    图7   c)定义填充计划。    图8   至此,表的全文索引已经建立完毕,表示只要键入SQL 指令就可以完成全文检索功能。   第三步,开发存储过程并把结果集分页,以供前台页面调用返回查询的结果。   1) 建立找资本全文检索储存过程USP_CaptialInfo_FullIndex。 /* 找资本全文索引开发过程  */ CREATE PROCEDURE USP_CaptialInfo_FullIndex ( @TableViewQueryNameVarchar( 1024 ), --传入的查询字符窜 @SearchKeyword nvarchar(100), --传入的查询关键字 @SelectStr Varchar( 500 ), --选择列字符串 @Criteria Varchar( 8000 ), --查询条件 @Sort Varchar( 255 ), --排序字符串 @FristTopNum int,  --显示的第一页置顶的数目 @Page bigint OUTPUT , --显示的当前页号 @CurrentPageRowbigint,  --页大小(显示多少行)  @TotalCount bigint output, --通过该查询条件,返回的查询记录的总页数 @Totaltimes bigint output --所有搜索时间,以秒为单位 ) as  DECLARE @starttime datetime, @endtime datetime SELECT @starttime = getdate() IF ISNULL(@SearchKeyword,'') !='' OR RTRIM(@SearchKeyword)!='' BEGIN SET @TableViewQueryName = ' SELECT '+ ' ROW_NUMBER() OVER (ORDER BY RANK DESC) AS SerialNumber ,'+ ' F.[rank], '+ ' p.*' + ' FROM'+ ' FREETEXTTABLE( CapitalInfoFactTab , (ProvinceName, CityName,  CountyName, Keyword,Title ,IndustryBName , shortcontent, ComAbout , ComBreif) , '+ ''''+@SearchKeyword+ ''''+') AS f '+ ' INNER JOIN  CapitalInfoFactTab  AS p '+ ' ON f.[key] = p.infoID ' EXEC [USP_GetFrontDataList_ByFullIndex] @TableViewQueryName, @SearchKeyword, @SelectStr, @Criteria, @Sort, @FristTopNum, @Page OUTPUT , @CurrentPageRow , @TotalCount OUTPUT END ELSE BEGIN EXEC dbo.GetFrontDataList 'dbo.ProjectInfoFactTab', 'InfoID', @SelectStr,@Criteria,@Sort,0, @Page output, @CurrentPageRow, @TotalCount output END SELECT @endtime = getdate() SELECT @Totaltimes = DATEdiff(Ms, @starttime ,@endtime) RETURN   2)建立通用分页存过程[USP_GetFrontDataList_ByFullIndex]。由于性能考虑,返回给前台页面需要网站数据库端即完成分页。    CREATE PROCEDURE [dbo].[USP_GetFrontDataList_ByFullIndex] ( @TableViewQueryName Varchar( 1024 ),  --Table或View或者Query的名字或字符串 @Key  Varchar( 50 ), --关键字 @SelectStr  Varchar( 500 ),  --选择列字符串 @Criteria  Varchar( 8000 ),--查询条件 @Sort  Varchar( 255 ), --排序字符串 @FristTopNum  INT,   --显示的第一页置顶的数目 @Page  BIGINT OUTPUT, --显示的当前页号 @CurrentPageRow BIGINT, --页大小(显示多少行) @TotalCount  BIGINT OUTPUT  --通过该查询条件,返回的查询记录的总页数 ) ASSET NOCOUNT ONif charindex(';',@Criteria)>0 or charindex('--',@Criteria)>0 or charindex('/*',@Criteria)>0 or charindex('*/',@Criteria)>0 or charindex('syscolumns',@Criteria)>0 orcharindex('sysfiles',@Criteria)>0 or charindex('char(124)',@Criteria)>0 or charindex('1=1',@Criteria)>0 RETURN DECLARE @TotalStr nVarchar(4000) DECLARE @Str  nVarchar(4000) DECLARE @TopRowNum bigint IF @SelectStr IS NULL AND RTRIM(LTRIM(@Criteria)) = '' SET @SelectStr = '*' IF @FristTopNum IS NULL AND @FristTopNum < 0 BEGIN SET @FristTopNum = 0 END ELSE IF @FristTopNum > @CurrentPageRow BEGIN SET @FristTopNum = @CurrentPageRow ENDIF @CurrentPageRow > 0 BEGIN IF @Criteria IS NOT NULL AND RTRIM(LTRIM(@Criteria)) <> '' BEGIN SET @TotalStr = 'SELECT @TotalCount=COUNT(*) FROM ' +'('+ @TableViewQueryName  +')'+ ' T ' + ' WHERE ' + @Criteria END ELSE BEGIN SET @TotalStr = 'SELECT @TotalCount=COUNT(*) FROM ' +'('+@TableViewQueryName +')'+ ' T ' END PRINT @TotalStr EXEC sp_ExecuteSql @TotalStr, N'@TotalCount bigint output',@TotalCount output SET @TotalCount = @TotalCount + isnull(@FristTopNum ,0) DECLARE @TotalPage bigint SET @TotalPage = @TotalCount/@CurrentPageRow IF @TotalCount%@CurrentPageRow > 0 BEGIN SET @TotalPage = @TotalPage + 1 END IF @Page <= 0 BEGIN SET @Page = 1 END IF @TotalPage > 0 AND @Page > @TotalPage BEGIN SET @Page = @TotalPage END--组织查询语句 SET @Str = 'SELECT  ' +  @SelectStr + ' FROM (' + @TableViewQueryName + ') T WHERE T.SerialNumber >' + cast ((@Page-1) as varchar(10)) + '*' +cast( @CurrentPageRow as varchar(10))+ ' AND T.SerialNumber <= '+ cast (@Page as varchar(10)) + '*' +cast( @CurrentPageRow as varchar(10))IF @Sort IS NOT NULL ANDRTRIM(LTRIM(@Sort)) <> '' BEGIN IF @Criteria IS NOT NULL AND RTRIM(LTRIM(@Criteria)) <> '' BEGIN SET @Str = @Str +  ' AND (' + @Criteria + ') ORDER BY '+@Sort END ELSE BEGIN SET @Str = @Str +  ' AND (' + @Criteria + ') ORDER BY '+@Sort END END ELSE BEGIN IF @Criteria IS NOT NULL AND  RTRIM(LTRIM(@Criteria)) <> '' BEGIN SET @str = @str + ' AND (' + @Criteria + ') '  END END --对无记录时当前页数的处理 IF @TotalCount=0 BEGIN SET @Page = 0 END END EXEC sp_ExecuteSql @Str 由于本行业网站可以提高如下几类信息资源,现列表分示如下: ID 检索内容 数据表 检索命令示例 1 投资 CapitalInfoTab DECLARE @RC int DECLARE @TableViewQueryName varchar(1024) DECLARE @SearchKeyword nvarchar(100) DECLARE @SelectStr varchar(500) DECLARE @Criteria varchar(8000) DECLARE @Sort varchar(255) DECLARE @FristTopNum int DECLARE @Page bigint DECLARE @CurrentPageRow bigint DECLARE @TotalCount bigint DECLARE @Totaltimes bigint   -- TODO: 在此处设置参数值。 SET @SearchKeyword = '地产项目' SET @SelectStr = '*' SET @Sort = '' SET @Page= 1 SET @CurrentPageRow = 20 EXECUTE @RC = [InvestDM].[dbo].USP_CapitalInfo_FullIndex   @TableViewQueryName  ,@SearchKeyword  ,@SelectStr  ,@Criteria  ,@Sort  ,@FristTopNum  ,@Page   ,@CurrentPageRow  ,@TotalCount OUTPUT  ,@Totaltimes OUTPUT SELECT @Page,@TotalCount,@Totaltimes 2 融资 ProjectInfoTab DECLARE @SearchKeyword nvarchar(100) --传入的查询关键字 SET   @SearchKeyword = '深圳'   SELECT p.title, p.infoid, f.[rank] , keyword,title,provinceName,cityName,CountyName FROM FREETEXTTABLE([ProjectInfoFactTab], (provinceName,cityName,CountyName,keyword,title), @SearchKeyword) AS f INNER JOIN [ProjectInfoFactTab] AS p ON f.[key] = p.infoID ORDER BY RANK DESC 3 招商 MerchantInfoTab   DECLARE @SearchKeyword nvarchar(100) --传入的查询关键字   SET   @SearchKeyword = '深圳'   SELECT  ROW_NUMBER() OVER (ORDER BY RANK DESC) AS SerialNumber , F.[rank], p.* FROM FREETEXTTABLE( MerchantInfoFactTab , (ProvinceName, CityName,  CountyName, Keyword,   Title ,IndustryBName , shortcontent, ZoneAbout , ZoneAboutBrief, MerchantTypeName ,MerchantAttributeName,   CooperationDemandName ) ,   @SearchKeyword) AS f INNER JOIN  MerchantInfoFactTab  AS p  ON f.[key] = p.infoID 4 资讯 NewsTab    DECLARE @SearchKeyword nvarchar(100) --传入的查询关键字    SET   @SearchKeyword = '深圳'    SELECT   ROW_NUMBER() OVER (ORDER BY RANK DESC) AS SerialNumber , F.[rank] ,  p.*  FROM   FREETEXTTABLE( NewsInfoFactTab , (AreaName,  Keyword,   Title , DisplayTitle, subtitle ,Summary , Content ,NewsIndustryName ,  NewsTypeName ) , @SearchKeyword ) AS f INNER JOIN  NewsInfoFactTab  AS p   ON f.[key] = p.infoID 

34,575

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧