olap4r 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +40 -0
- data/README.md +69 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/lib/olap4j.jar +0 -0
- data/lib/olap4r.rb +17 -0
- data/lib/olap4r/cellset.rb +59 -0
- data/lib/olap4r/connection.rb +161 -0
- data/lib/olap4r/query_builder.rb +131 -0
- data/lib/olap4r/rowset.rb +37 -0
- data/olap4r.gemspec +75 -0
- data/spec/config.yml.example +6 -0
- data/spec/connection_spec.rb +232 -0
- data/spec/fixtures/FoodMart.xml +802 -0
- data/spec/query_builder_spec.rb +270 -0
- data/spec/spec_helper.rb +18 -0
- metadata +151 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
module Olap
|
2
|
+
class RowSet
|
3
|
+
def initialize rowset
|
4
|
+
@rowset = rowset
|
5
|
+
end
|
6
|
+
|
7
|
+
# Returns list of columns
|
8
|
+
#
|
9
|
+
def columns
|
10
|
+
@columns ||= 1.upto(@rowset.get_meta_data.get_column_count).map do |i|
|
11
|
+
{
|
12
|
+
:id => @rowset.get_meta_data.getColumnName(i),
|
13
|
+
:name => @rowset.get_meta_data.getColumnLabel(i)
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns query values
|
19
|
+
#
|
20
|
+
# ==== Attributes
|
21
|
+
#
|
22
|
+
# * +value_type+ - Returned value type (:value or :formatted_value)
|
23
|
+
#
|
24
|
+
def values value_type = :formatted_value
|
25
|
+
return @values unless @values.nil?
|
26
|
+
|
27
|
+
@values = []
|
28
|
+
while @rowset.next do
|
29
|
+
@values << 1.upto(self.columns.size).map do |i|
|
30
|
+
@rowset.getString i
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
@values
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/olap4r.gemspec
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "olap4r"
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Filip Tepper"]
|
12
|
+
s.date = "2012-08-20"
|
13
|
+
s.description = "olap4j wrapper for JRuby"
|
14
|
+
s.email = "filip@tepper.pl"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".rspec",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"README.md",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/olap4j.jar",
|
27
|
+
"lib/olap4r.rb",
|
28
|
+
"lib/olap4r/cellset.rb",
|
29
|
+
"lib/olap4r/connection.rb",
|
30
|
+
"lib/olap4r/query_builder.rb",
|
31
|
+
"lib/olap4r/rowset.rb",
|
32
|
+
"olap4r.gemspec",
|
33
|
+
"spec/config.yml.example",
|
34
|
+
"spec/connection_spec.rb",
|
35
|
+
"spec/fixtures/FoodMart.xml",
|
36
|
+
"spec/query_builder_spec.rb",
|
37
|
+
"spec/spec_helper.rb"
|
38
|
+
]
|
39
|
+
s.homepage = "http://github.com/Freeport-Metrics/olap4r"
|
40
|
+
s.licenses = ["MIT"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = "1.8.24"
|
43
|
+
s.summary = "olap4j wrapper for JRuby"
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
s.specification_version = 3
|
47
|
+
|
48
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
+
s.add_development_dependency(%q<jruby-openssl>, [">= 0"])
|
50
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.11.0"])
|
51
|
+
s.add_development_dependency(%q<yard>, ["~> 0.8.2.1"])
|
52
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.1.0"])
|
53
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
54
|
+
s.add_development_dependency(%q<olap4r-mondrian>, ["~> 0.1.0"])
|
55
|
+
s.add_development_dependency(%q<olap4r-xmla>, ["~> 0.1.0"])
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<jruby-openssl>, [">= 0"])
|
58
|
+
s.add_dependency(%q<rspec>, ["~> 2.11.0"])
|
59
|
+
s.add_dependency(%q<yard>, ["~> 0.8.2.1"])
|
60
|
+
s.add_dependency(%q<bundler>, ["~> 1.1.0"])
|
61
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
62
|
+
s.add_dependency(%q<olap4r-mondrian>, ["~> 0.1.0"])
|
63
|
+
s.add_dependency(%q<olap4r-xmla>, ["~> 0.1.0"])
|
64
|
+
end
|
65
|
+
else
|
66
|
+
s.add_dependency(%q<jruby-openssl>, [">= 0"])
|
67
|
+
s.add_dependency(%q<rspec>, ["~> 2.11.0"])
|
68
|
+
s.add_dependency(%q<yard>, ["~> 0.8.2.1"])
|
69
|
+
s.add_dependency(%q<bundler>, ["~> 1.1.0"])
|
70
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
71
|
+
s.add_dependency(%q<olap4r-mondrian>, ["~> 0.1.0"])
|
72
|
+
s.add_dependency(%q<olap4r-xmla>, ["~> 0.1.0"])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
mondrian:
|
2
|
+
jdbc_driver_path: "/usr/local/Cellar/tomcat/7.0.6//libexec/common/endorsed/mysql-connector-java-5.1.15-bin"
|
3
|
+
connection_string: "jdbc:mondrian:JdbcDrivers=com.mysql.jdbc.Driver;Jdbc=jdbc:mysql://localhost/mondrian_foodmart?user=root;Catalog=file:spec/fixtures/FoodMart.xml;"
|
4
|
+
|
5
|
+
xmla:
|
6
|
+
connection_string: "jdbc:xmla:Server=http://127.0.0.1:8080/mondrian/xmla;Catalog=FoodMart;"
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
shared_examples_for "an Olap::Connection driver" do
|
4
|
+
context "given an instance" do
|
5
|
+
context "#cubes" do
|
6
|
+
it "returns an array of cubes" do
|
7
|
+
connection.cubes.should =~ [
|
8
|
+
{ :unique_name => "[Sales Ragged]", :name => "Sales Ragged" },
|
9
|
+
{ :unique_name => "[Warehouse]", :name => "Warehouse" },
|
10
|
+
{ :unique_name => "[HR]", :name => "HR" },
|
11
|
+
{ :unique_name => "[Warehouse and Sales]", :name => "Warehouse and Sales" },
|
12
|
+
{ :unique_name => "[Sales 2]", :name => "Sales 2" },
|
13
|
+
{ :unique_name => "[Store]", :name => "Store" },
|
14
|
+
{ :unique_name => "[Sales]", :name => "Sales" }
|
15
|
+
]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "#measures" do
|
20
|
+
it "returns an array of measures" do
|
21
|
+
connection.measures("[HR]").should =~ [
|
22
|
+
{ :unique_name => "[Measures].[Org Salary]", :name => "Org Salary" },
|
23
|
+
{ :unique_name => "[Measures].[Count]", :name => "Count" },
|
24
|
+
{ :unique_name => "[Measures].[Number of Employees]", :name => "Number of Employees" },
|
25
|
+
{ :unique_name => "[Measures].[Employee Salary]", :name => "Employee Salary" },
|
26
|
+
{ :unique_name => "[Measures].[Avg Salary]", :name => "Avg Salary" }
|
27
|
+
]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "#dimensions" do
|
32
|
+
it "returns an array of dimensions" do
|
33
|
+
connection.dimensions("[Sales 2]").length.should == 4
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns dimensions with type" do
|
37
|
+
dimensions = connection.dimensions "[Sales 2]"
|
38
|
+
dimensions[0][:type].should == :measure
|
39
|
+
dimensions[1][:type].should == :time
|
40
|
+
dimensions[2][:type].should == :other
|
41
|
+
dimensions[3][:type].should == :other
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "#children_lookup" do
|
46
|
+
it "returns an array of dimensions for null member" do
|
47
|
+
connection.children_lookup("[Sales Ragged]").should =~ [
|
48
|
+
{ :unique_name => "[Measures]", :name => "Measures", :children => true, :type => :measure },
|
49
|
+
{ :unique_name => "[Store]", :name => "Store", :children => true, :type => :other },
|
50
|
+
{ :unique_name => "[Geography]", :name => "Geography", :children => true, :type => :other },
|
51
|
+
{ :unique_name => "[Store Size in SQFT]", :name => "Store Size in SQFT", :children => true, :type => :other },
|
52
|
+
{ :unique_name => "[Store Type]", :name => "Store Type", :children => true, :type => :other },
|
53
|
+
{ :unique_name => "[Time]", :name => "Time", :children => true, :type => :time },
|
54
|
+
{ :unique_name => "[Product]", :name => "Product", :children => true, :type => :other },
|
55
|
+
{ :unique_name => "[Promotion Media]", :name => "Promotion Media", :children => true, :type => :other },
|
56
|
+
{ :unique_name => "[Promotions]", :name => "Promotions", :children => true, :type => :other },
|
57
|
+
{ :unique_name => "[Customers]", :name => "Customers", :children => true, :type => :other },
|
58
|
+
{ :unique_name => "[Education Level]", :name => "Education Level", :children => true, :type => :other },
|
59
|
+
{ :unique_name => "[Gender]", :name => "Gender", :children => true, :type => :other },
|
60
|
+
{ :unique_name => "[Marital Status]", :name => "Marital Status", :children => true, :type => :other },
|
61
|
+
{ :unique_name => "[Yearly Income]", :name => "Yearly Income", :children => true, :type => :other }
|
62
|
+
]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns an array of dimensions for a given first member in hierarchy" do
|
66
|
+
connection.children_lookup("[Sales Ragged]", "[Store]").should =~ [
|
67
|
+
{ :unique_name => "[Store].[All Stores]", :name => "All Stores", :children => true }
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
it "returns an array of children for a given member in hierarchy" do
|
72
|
+
connection.children_lookup("[Sales Ragged]", "[Store].[All Stores].[USA].[CA]").should =~ [
|
73
|
+
{ :unique_name => "[Store].[USA].[CA].[Alameda]", :name => "Alameda", :children => true },
|
74
|
+
{ :unique_name => "[Store].[USA].[CA].[Beverly Hills]", :name => "Beverly Hills", :children => true },
|
75
|
+
{ :unique_name => "[Store].[USA].[CA].[Los Angeles]", :name => "Los Angeles", :children => true },
|
76
|
+
{ :unique_name => "[Store].[USA].[CA].[San Francisco]", :name => "San Francisco", :children => true }
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns an array of children for a given measures member in hierarchy" do
|
81
|
+
connection.children_lookup("[Sales Ragged]", "[Measures]").should =~ [
|
82
|
+
{ :unique_name => "[Measures].[Unit Sales]", :name => "Unit Sales", :children => false },
|
83
|
+
{ :unique_name => "[Measures].[Store Cost]", :name => "Store Cost", :children => false },
|
84
|
+
{ :unique_name => "[Measures].[Store Sales]", :name => "Store Sales", :children => false },
|
85
|
+
{ :unique_name => "[Measures].[Sales Count]", :name => "Sales Count", :children => false },
|
86
|
+
{ :unique_name => "[Measures].[Customer Count]", :name => "Customer Count", :children => false }
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "recursively returns an array of children for a given dimension" do
|
91
|
+
dimension = connection.children_lookup "[Sales Ragged]", "[Time]", true
|
92
|
+
dimension[0][:children].should be_an(Array)
|
93
|
+
dimension[0][:children][0][:children].should be_an(Array)
|
94
|
+
dimension[0][:children][0][:children][0][:children].should be_an(Array)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "#execute" do
|
99
|
+
let(:cellset) { connection.execute "SELECT [Measures].[Unit Sales] ON COLUMNS, [Store] ON ROWS FROM [Sales]" }
|
100
|
+
|
101
|
+
it "returns Olap::CellSet instance for successful queries" do
|
102
|
+
cellset.should be_a(Olap::CellSet)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "returns cellset axes" do
|
106
|
+
cellset.axes.should =~ [
|
107
|
+
{ :axis => :columns, :values => [
|
108
|
+
[{ :name => "Unit Sales", :unique_name => "[Measures].[Unit Sales]", :drillable => false }]
|
109
|
+
] },
|
110
|
+
{ :axis => :rows, :values => [
|
111
|
+
[{ :name => "All Stores", :unique_name => "[Store].[All Stores]", :drillable => true }]
|
112
|
+
] }
|
113
|
+
]
|
114
|
+
end
|
115
|
+
|
116
|
+
it "returns cellset formatted values" do
|
117
|
+
cellset.values.should =~ [["266,773"]]
|
118
|
+
end
|
119
|
+
|
120
|
+
it "returns cellset raw values" do
|
121
|
+
cellset.values(:value).should =~ [[266773.0]]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "#execute drill-down query" do
|
126
|
+
let(:cellset) { connection.execute %{
|
127
|
+
SELECT {[Measures].[Unit Sales], [Measures].[Store Cost], [Measures].[Store Sales]} ON COLUMNS,
|
128
|
+
HIERARCHIZE(UNION(CROSSJOIN({[Promotion Media].[All Media]}, {[Product].[All Products]}), CROSSJOIN({[Promotion Media].[All Media]}, [Product].[All Products].Children))) ON ROWS
|
129
|
+
FROM [Sales]
|
130
|
+
WHERE [Time].[1997]
|
131
|
+
} }
|
132
|
+
|
133
|
+
it "returns cellset axes" do
|
134
|
+
cellset.axes.should =~ [
|
135
|
+
{
|
136
|
+
:axis => :columns,
|
137
|
+
:values => [
|
138
|
+
[{ :name => "Unit Sales", :unique_name => "[Measures].[Unit Sales]", :drillable => false }],
|
139
|
+
[{ :name => "Store Cost", :unique_name => "[Measures].[Store Cost]", :drillable => false }],
|
140
|
+
[{ :name => "Store Sales", :unique_name => "[Measures].[Store Sales]", :drillable => false}
|
141
|
+
]]
|
142
|
+
},
|
143
|
+
{
|
144
|
+
:axis => :rows, :values => [
|
145
|
+
[
|
146
|
+
{ :name => "All Media", :unique_name => "[Promotion Media].[All Media]", :drillable => true},
|
147
|
+
{ :name => "All Products", :unique_name => "[Product].[All Products]", :drillable => true }
|
148
|
+
], [
|
149
|
+
{ :name => "All Media", :unique_name => "[Promotion Media].[All Media]", :drillable => true },
|
150
|
+
{ :name => "Drink", :unique_name => "[Product].[Drink]", :drillable => true }
|
151
|
+
], [
|
152
|
+
{ :name => "All Media", :unique_name => "[Promotion Media].[All Media]", :drillable => true },
|
153
|
+
{ :name => "Food", :unique_name => "[Product].[Food]", :drillable => true}
|
154
|
+
], [
|
155
|
+
{ :name => "All Media", :unique_name => "[Promotion Media].[All Media]", :drillable => true },
|
156
|
+
{ :name => "Non-Consumable", :unique_name => "[Product].[Non-Consumable]", :drillable => true }
|
157
|
+
]
|
158
|
+
]
|
159
|
+
}
|
160
|
+
]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
shared_examples_for "an Olap::Connection driver with drillthrough capabilities" do
|
167
|
+
context "given an instance" do
|
168
|
+
context "#drillthrough" do
|
169
|
+
let(:rowset) { connection.drillthrough "DRILLTHROUGH SELECT [Measures].[Unit Sales] ON COLUMNS, [Store] ON ROWS FROM [Sales]" }
|
170
|
+
|
171
|
+
it "returns Olap::RowSet instance for successful queries" do
|
172
|
+
rowset.should be_a(Olap::RowSet)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "returns rawset axes" do
|
176
|
+
rowset.columns.should include(
|
177
|
+
{ :id => "the_year", :name => "Year" },
|
178
|
+
{ :id => "unit_sales", :name => "Unit Sales" }
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "returns rawset values" do
|
183
|
+
rowset.values.length.should == 86837
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe Olap::Connection, "for invalid connection string" do
|
190
|
+
context "#initialize" do
|
191
|
+
it "raises an Exception for 'jdbc' connection string" do
|
192
|
+
lambda {
|
193
|
+
connection = Olap::Connection.new "jdbc"
|
194
|
+
}.should raise_error(Olap::InvalidConnectionStringException)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "raised an Exception for 'jdbc:invalid:foo' connection string" do
|
198
|
+
lambda {
|
199
|
+
connection = Olap::Connection.new "jdbc:invalid:foo"
|
200
|
+
}.should raise_error(Olap::InvalidOlapDriverException)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe Olap::Connection, "for Mondrian driver" do
|
206
|
+
context "#initialize" do
|
207
|
+
it "returns Olap::Connection instance for successful connection" do
|
208
|
+
connection = Olap::Connection.new RSPEC_CONFIG["mondrian"]["connection_string"]
|
209
|
+
connection.should be_a(Olap::Connection)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context "given an instance" do
|
214
|
+
let(:connection) { Olap::Connection.new RSPEC_CONFIG["mondrian"]["connection_string"] }
|
215
|
+
it_should_behave_like "an Olap::Connection driver"
|
216
|
+
it_should_behave_like "an Olap::Connection driver with drillthrough capabilities"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe Olap::Connection, "for XML/A driver" do
|
221
|
+
context "#initialize" do
|
222
|
+
it "returns Olap::Connection instance for successful connection" do
|
223
|
+
connection = Olap::Connection.new RSPEC_CONFIG["xmla"]["connection_string"]
|
224
|
+
connection.should be_a(Olap::Connection)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context "given an instance" do
|
229
|
+
let(:connection) { Olap::Connection.new RSPEC_CONFIG["xmla"]["connection_string"] }
|
230
|
+
it_should_behave_like "an Olap::Connection driver"
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,802 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<Schema name="FoodMart">
|
3
|
+
<!--
|
4
|
+
== $Id: //open/mondrian-release/3.2/demo/FoodMart.xml#2 $
|
5
|
+
== This software is subject to the terms of the Eclipse Public License v1.0
|
6
|
+
== Agreement, available at the following URL:
|
7
|
+
== http://www.eclipse.org/legal/epl-v10.html.
|
8
|
+
== Copyright (C) 2000-2002 Kana Software, Inc.
|
9
|
+
== Copyright (C) 2002-2009 Julian Hyde and others
|
10
|
+
== All Rights Reserved.
|
11
|
+
== You must accept the terms of that agreement to use this software.
|
12
|
+
-->
|
13
|
+
|
14
|
+
<!-- Shared dimensions -->
|
15
|
+
|
16
|
+
<Dimension name="Store">
|
17
|
+
<Hierarchy hasAll="true" primaryKey="store_id">
|
18
|
+
<Table name="store"/>
|
19
|
+
<Level name="Store Country" column="store_country" uniqueMembers="true"/>
|
20
|
+
<Level name="Store State" column="store_state" uniqueMembers="true"/>
|
21
|
+
<Level name="Store City" column="store_city" uniqueMembers="false"/>
|
22
|
+
<Level name="Store Name" column="store_name" uniqueMembers="true">
|
23
|
+
<Property name="Store Type" column="store_type"/>
|
24
|
+
<Property name="Store Manager" column="store_manager"/>
|
25
|
+
<Property name="Store Sqft" column="store_sqft" type="Numeric"/>
|
26
|
+
<Property name="Grocery Sqft" column="grocery_sqft" type="Numeric"/>
|
27
|
+
<Property name="Frozen Sqft" column="frozen_sqft" type="Numeric"/>
|
28
|
+
<Property name="Meat Sqft" column="meat_sqft" type="Numeric"/>
|
29
|
+
<Property name="Has coffee bar" column="coffee_bar" type="Boolean"/>
|
30
|
+
<Property name="Street address" column="store_street_address" type="String"/>
|
31
|
+
</Level>
|
32
|
+
</Hierarchy>
|
33
|
+
</Dimension>
|
34
|
+
|
35
|
+
<Dimension name="Store Size in SQFT">
|
36
|
+
<Hierarchy hasAll="true" primaryKey="store_id">
|
37
|
+
<Table name="store"/>
|
38
|
+
<Level name="Store Sqft" column="store_sqft" type="Numeric" uniqueMembers="true"/>
|
39
|
+
</Hierarchy>
|
40
|
+
</Dimension>
|
41
|
+
|
42
|
+
<Dimension name="Store Type">
|
43
|
+
<Hierarchy hasAll="true" primaryKey="store_id">
|
44
|
+
<Table name="store"/>
|
45
|
+
<Level name="Store Type" column="store_type" uniqueMembers="true"/>
|
46
|
+
</Hierarchy>
|
47
|
+
</Dimension>
|
48
|
+
|
49
|
+
<Dimension name="Time" type="TimeDimension">
|
50
|
+
<Hierarchy hasAll="false" primaryKey="time_id">
|
51
|
+
<Table name="time_by_day"/>
|
52
|
+
<Level name="Year" column="the_year" type="Numeric" uniqueMembers="true"
|
53
|
+
levelType="TimeYears"/>
|
54
|
+
<Level name="Quarter" column="quarter" uniqueMembers="false"
|
55
|
+
levelType="TimeQuarters"/>
|
56
|
+
<Level name="Month" column="month_of_year" uniqueMembers="false" type="Numeric"
|
57
|
+
levelType="TimeMonths"/>
|
58
|
+
</Hierarchy>
|
59
|
+
<Hierarchy hasAll="true" name="Weekly" primaryKey="time_id">
|
60
|
+
<Table name="time_by_day"/>
|
61
|
+
<Level name="Year" column="the_year" type="Numeric" uniqueMembers="true"
|
62
|
+
levelType="TimeYears"/>
|
63
|
+
<Level name="Week" column="week_of_year" type="Numeric" uniqueMembers="false"
|
64
|
+
levelType="TimeWeeks"/>
|
65
|
+
<Level name="Day" column="day_of_month" uniqueMembers="false" type="Numeric"
|
66
|
+
levelType="TimeDays"/>
|
67
|
+
</Hierarchy>
|
68
|
+
</Dimension>
|
69
|
+
|
70
|
+
<Dimension name="Product">
|
71
|
+
<Hierarchy hasAll="true" primaryKey="product_id" primaryKeyTable="product">
|
72
|
+
<Join leftKey="product_class_id" rightKey="product_class_id">
|
73
|
+
<Table name="product"/>
|
74
|
+
<Table name="product_class"/>
|
75
|
+
</Join>
|
76
|
+
<!--
|
77
|
+
<Query>
|
78
|
+
<SQL dialect="generic">
|
79
|
+
SELECT *
|
80
|
+
FROM "product", "product_class"
|
81
|
+
WHERE "product"."product_class_id" = "product_class"."product_class_id"
|
82
|
+
</SQL>
|
83
|
+
</Query>
|
84
|
+
<Level name="Product Family" column="product_family" uniqueMembers="true"/>
|
85
|
+
<Level name="Product Department" column="product_department" uniqueMembers="false"/>
|
86
|
+
<Level name="Product Category" column="product_category" uniqueMembers="false"/>
|
87
|
+
<Level name="Product Subcategory" column="product_subcategory" uniqueMembers="false"/>
|
88
|
+
<Level name="Brand Name" column="brand_name" uniqueMembers="false"/>
|
89
|
+
<Level name="Product Name" column="product_name" uniqueMembers="true"/>
|
90
|
+
-->
|
91
|
+
<Level name="Product Family" table="product_class" column="product_family"
|
92
|
+
uniqueMembers="true"/>
|
93
|
+
<Level name="Product Department" table="product_class" column="product_department"
|
94
|
+
uniqueMembers="false"/>
|
95
|
+
<Level name="Product Category" table="product_class" column="product_category"
|
96
|
+
uniqueMembers="false"/>
|
97
|
+
<Level name="Product Subcategory" table="product_class" column="product_subcategory"
|
98
|
+
uniqueMembers="false"/>
|
99
|
+
<Level name="Brand Name" table="product" column="brand_name" uniqueMembers="false"/>
|
100
|
+
<Level name="Product Name" table="product" column="product_name"
|
101
|
+
uniqueMembers="true"/>
|
102
|
+
</Hierarchy>
|
103
|
+
</Dimension>
|
104
|
+
|
105
|
+
<Dimension name="Warehouse">
|
106
|
+
<Hierarchy hasAll="true" primaryKey="warehouse_id">
|
107
|
+
<Table name="warehouse"/>
|
108
|
+
<Level name="Country" column="warehouse_country" uniqueMembers="true"/>
|
109
|
+
<Level name="State Province" column="warehouse_state_province"
|
110
|
+
uniqueMembers="true"/>
|
111
|
+
<Level name="City" column="warehouse_city" uniqueMembers="false"/>
|
112
|
+
<Level name="Warehouse Name" column="warehouse_name" uniqueMembers="true"/>
|
113
|
+
</Hierarchy>
|
114
|
+
</Dimension>
|
115
|
+
|
116
|
+
<!-- Sales -->
|
117
|
+
<Cube name="Sales" defaultMeasure="Unit Sales">
|
118
|
+
<Table name="sales_fact_1997">
|
119
|
+
<!--
|
120
|
+
<AggExclude name="agg_l_03_sales_fact_1997" />
|
121
|
+
<AggExclude name="agg_ll_01_sales_fact_1997" />
|
122
|
+
<AggExclude name="agg_pl_01_sales_fact_1997" />
|
123
|
+
<AggExclude name="agg_l_05_sales_fact_1997" />
|
124
|
+
-->
|
125
|
+
<AggExclude name="agg_c_special_sales_fact_1997" />
|
126
|
+
<!--
|
127
|
+
<AggExclude name="agg_c_14_sales_fact_1997" />
|
128
|
+
-->
|
129
|
+
<AggExclude name="agg_lc_100_sales_fact_1997" />
|
130
|
+
<AggExclude name="agg_lc_10_sales_fact_1997" />
|
131
|
+
<AggExclude name="agg_pc_10_sales_fact_1997" />
|
132
|
+
<AggName name="agg_c_special_sales_fact_1997">
|
133
|
+
<AggFactCount column="FACT_COUNT"/>
|
134
|
+
<AggIgnoreColumn column="foo"/>
|
135
|
+
<AggIgnoreColumn column="bar"/>
|
136
|
+
<AggForeignKey factColumn="product_id" aggColumn="PRODUCT_ID" />
|
137
|
+
<AggForeignKey factColumn="customer_id" aggColumn="CUSTOMER_ID" />
|
138
|
+
<AggForeignKey factColumn="promotion_id" aggColumn="PROMOTION_ID" />
|
139
|
+
<AggForeignKey factColumn="store_id" aggColumn="STORE_ID" />
|
140
|
+
<!--
|
141
|
+
<AggMeasure name="[Measures].[Avg Unit Sales]" column="UNIT_SALES_AVG"/>
|
142
|
+
-->
|
143
|
+
<AggMeasure name="[Measures].[Unit Sales]" column="UNIT_SALES_SUM" />
|
144
|
+
<AggMeasure name="[Measures].[Store Cost]" column="STORE_COST_SUM" />
|
145
|
+
<AggMeasure name="[Measures].[Store Sales]" column="STORE_SALES_SUM" />
|
146
|
+
<AggLevel name="[Time].[Year]" column="TIME_YEAR" />
|
147
|
+
<AggLevel name="[Time].[Quarter]" column="TIME_QUARTER" />
|
148
|
+
<AggLevel name="[Time].[Month]" column="TIME_MONTH" />
|
149
|
+
</AggName>
|
150
|
+
</Table>
|
151
|
+
|
152
|
+
<DimensionUsage name="Store" source="Store" foreignKey="store_id"/>
|
153
|
+
<DimensionUsage name="Store Size in SQFT" source="Store Size in SQFT"
|
154
|
+
foreignKey="store_id"/>
|
155
|
+
<DimensionUsage name="Store Type" source="Store Type" foreignKey="store_id"/>
|
156
|
+
<DimensionUsage name="Time" source="Time" foreignKey="time_id"/>
|
157
|
+
<DimensionUsage name="Product" source="Product" foreignKey="product_id"/>
|
158
|
+
<Dimension name="Promotion Media" foreignKey="promotion_id">
|
159
|
+
<Hierarchy hasAll="true" allMemberName="All Media" primaryKey="promotion_id" defaultMember="All Media">
|
160
|
+
<Table name="promotion"/>
|
161
|
+
<Level name="Media Type" column="media_type" uniqueMembers="true"/>
|
162
|
+
</Hierarchy>
|
163
|
+
</Dimension>
|
164
|
+
<Dimension name="Promotions" foreignKey="promotion_id">
|
165
|
+
<Hierarchy hasAll="true" allMemberName="All Promotions" primaryKey="promotion_id" defaultMember="[All Promotions]">
|
166
|
+
<Table name="promotion"/>
|
167
|
+
<Level name="Promotion Name" column="promotion_name" uniqueMembers="true"/>
|
168
|
+
</Hierarchy>
|
169
|
+
</Dimension>
|
170
|
+
<Dimension name="Customers" foreignKey="customer_id">
|
171
|
+
<Hierarchy hasAll="true" allMemberName="All Customers" primaryKey="customer_id">
|
172
|
+
<Table name="customer"/>
|
173
|
+
<Level name="Country" column="country" uniqueMembers="true"/>
|
174
|
+
<Level name="State Province" column="state_province" uniqueMembers="true"/>
|
175
|
+
<Level name="City" column="city" uniqueMembers="false"/>
|
176
|
+
<Level name="Name" column="customer_id" type="Numeric" uniqueMembers="true">
|
177
|
+
<NameExpression>
|
178
|
+
<SQL dialect="oracle">
|
179
|
+
"fname" || ' ' || "lname"
|
180
|
+
</SQL>
|
181
|
+
<SQL dialect="hsqldb">
|
182
|
+
"fname" || ' ' || "lname"
|
183
|
+
</SQL>
|
184
|
+
<SQL dialect="access">
|
185
|
+
fname + ' ' + lname
|
186
|
+
</SQL>
|
187
|
+
<SQL dialect="postgres">
|
188
|
+
"fname" || ' ' || "lname"
|
189
|
+
</SQL>
|
190
|
+
<SQL dialect="mysql">
|
191
|
+
CONCAT(`customer`.`fname`, ' ', `customer`.`lname`)
|
192
|
+
</SQL>
|
193
|
+
<SQL dialect="mssql">
|
194
|
+
fname + ' ' + lname
|
195
|
+
</SQL>
|
196
|
+
<SQL dialect="derby">
|
197
|
+
"customer"."fullname"
|
198
|
+
</SQL>
|
199
|
+
<SQL dialect="db2">
|
200
|
+
CONCAT(CONCAT("customer"."fname", ' '), "customer"."lname")
|
201
|
+
</SQL>
|
202
|
+
<SQL dialect="luciddb">
|
203
|
+
"fname" || ' ' || "lname"
|
204
|
+
</SQL>
|
205
|
+
<SQL dialect="neoview">
|
206
|
+
"customer"."fullname"
|
207
|
+
</SQL>
|
208
|
+
<SQL dialect="teradata">
|
209
|
+
"fname" || ' ' || "lname"
|
210
|
+
</SQL>
|
211
|
+
<SQL dialect="generic">
|
212
|
+
fullname
|
213
|
+
</SQL>
|
214
|
+
</NameExpression>
|
215
|
+
<OrdinalExpression>
|
216
|
+
<SQL dialect="oracle">
|
217
|
+
"fname" || ' ' || "lname"
|
218
|
+
</SQL>
|
219
|
+
<SQL dialect="hsqldb">
|
220
|
+
"fname" || ' ' || "lname"
|
221
|
+
</SQL>
|
222
|
+
<SQL dialect="access">
|
223
|
+
fname + ' ' + lname
|
224
|
+
</SQL>
|
225
|
+
<SQL dialect="postgres">
|
226
|
+
"fname" || ' ' || "lname"
|
227
|
+
</SQL>
|
228
|
+
<SQL dialect="mysql">
|
229
|
+
CONCAT(`customer`.`fname`, ' ', `customer`.`lname`)
|
230
|
+
</SQL>
|
231
|
+
<SQL dialect="mssql">
|
232
|
+
fname + ' ' + lname
|
233
|
+
</SQL>
|
234
|
+
<SQL dialect="neoview">
|
235
|
+
"customer"."fullname"
|
236
|
+
</SQL>
|
237
|
+
<SQL dialect="derby">
|
238
|
+
"customer"."fullname"
|
239
|
+
</SQL>
|
240
|
+
<SQL dialect="db2">
|
241
|
+
CONCAT(CONCAT("customer"."fname", ' '), "customer"."lname")
|
242
|
+
</SQL>
|
243
|
+
<SQL dialect="luciddb">
|
244
|
+
"fname" || ' ' || "lname"
|
245
|
+
</SQL>
|
246
|
+
<SQL dialect="generic">
|
247
|
+
fullname
|
248
|
+
</SQL>
|
249
|
+
</OrdinalExpression>
|
250
|
+
<Property name="Gender" column="gender"/>
|
251
|
+
<Property name="Marital Status" column="marital_status"/>
|
252
|
+
<Property name="Education" column="education"/>
|
253
|
+
<Property name="Yearly Income" column="yearly_income"/>
|
254
|
+
</Level>
|
255
|
+
</Hierarchy>
|
256
|
+
</Dimension>
|
257
|
+
<Dimension name="Education Level" foreignKey="customer_id">
|
258
|
+
<Hierarchy hasAll="true" primaryKey="customer_id">
|
259
|
+
<Table name="customer"/>
|
260
|
+
<Level name="Education Level" column="education" uniqueMembers="true"/>
|
261
|
+
</Hierarchy>
|
262
|
+
</Dimension>
|
263
|
+
<Dimension name="Gender" foreignKey="customer_id">
|
264
|
+
<Hierarchy hasAll="true" allMemberName="All Gender" primaryKey="customer_id">
|
265
|
+
<Table name="customer"/>
|
266
|
+
<Level name="Gender" column="gender" uniqueMembers="true"/>
|
267
|
+
</Hierarchy>
|
268
|
+
</Dimension>
|
269
|
+
<Dimension name="Marital Status" foreignKey="customer_id">
|
270
|
+
<Hierarchy hasAll="true" allMemberName="All Marital Status" primaryKey="customer_id">
|
271
|
+
<Table name="customer"/>
|
272
|
+
<Level name="Marital Status" column="marital_status" uniqueMembers="true" approxRowCount="111"/>
|
273
|
+
</Hierarchy>
|
274
|
+
</Dimension>
|
275
|
+
<Dimension name="Yearly Income" foreignKey="customer_id">
|
276
|
+
<Hierarchy hasAll="true" primaryKey="customer_id">
|
277
|
+
<Table name="customer"/>
|
278
|
+
<Level name="Yearly Income" column="yearly_income" uniqueMembers="true"/>
|
279
|
+
</Hierarchy>
|
280
|
+
</Dimension>
|
281
|
+
|
282
|
+
<Measure name="Unit Sales" column="unit_sales" aggregator="sum"
|
283
|
+
formatString="Standard"/>
|
284
|
+
<Measure name="Store Cost" column="store_cost" aggregator="sum"
|
285
|
+
formatString="#,###.00"/>
|
286
|
+
<Measure name="Store Sales" column="store_sales" aggregator="sum"
|
287
|
+
formatString="#,###.00"/>
|
288
|
+
<Measure name="Sales Count" column="product_id" aggregator="count"
|
289
|
+
formatString="#,###"/>
|
290
|
+
<Measure name="Customer Count" column="customer_id"
|
291
|
+
aggregator="distinct-count" formatString="#,###"/>
|
292
|
+
<Measure name="Promotion Sales" aggregator="sum" formatString="#,###.00">
|
293
|
+
<MeasureExpression>
|
294
|
+
<SQL dialect="access">
|
295
|
+
Iif("sales_fact_1997"."promotion_id" = 0, 0, "sales_fact_1997"."store_sales")
|
296
|
+
</SQL>
|
297
|
+
<SQL dialect="oracle">
|
298
|
+
(case when "sales_fact_1997"."promotion_id" = 0 then 0 else "sales_fact_1997"."store_sales" end)
|
299
|
+
</SQL>
|
300
|
+
<SQL dialect="hsqldb">
|
301
|
+
(case when "sales_fact_1997"."promotion_id" = 0 then 0 else "sales_fact_1997"."store_sales" end)
|
302
|
+
</SQL>
|
303
|
+
<SQL dialect="postgres">
|
304
|
+
(case when "sales_fact_1997"."promotion_id" = 0 then 0 else "sales_fact_1997"."store_sales" end)
|
305
|
+
</SQL>
|
306
|
+
<SQL dialect="mysql">
|
307
|
+
(case when `sales_fact_1997`.`promotion_id` = 0 then 0 else `sales_fact_1997`.`store_sales` end)
|
308
|
+
</SQL>
|
309
|
+
<!-- Workaround the fact that Infobright does not have a CASE operator.
|
310
|
+
The simpler expression gives wrong results, so some tests are
|
311
|
+
disabled. -->
|
312
|
+
<SQL dialect="neoview">
|
313
|
+
(case when "sales_fact_1997"."promotion_id" = 0 then 0 else "sales_fact_1997"."store_sales" end)
|
314
|
+
</SQL>
|
315
|
+
<SQL dialect="infobright">
|
316
|
+
`sales_fact_1997`.`store_sales`
|
317
|
+
</SQL>
|
318
|
+
<SQL dialect="derby">
|
319
|
+
(case when "sales_fact_1997"."promotion_id" = 0 then 0 else "sales_fact_1997"."store_sales" end)
|
320
|
+
</SQL>
|
321
|
+
<SQL dialect="luciddb">
|
322
|
+
(case when "sales_fact_1997"."promotion_id" = 0 then 0 else "sales_fact_1997"."store_sales" end)
|
323
|
+
</SQL>
|
324
|
+
<SQL dialect="db2">
|
325
|
+
(case when "sales_fact_1997"."promotion_id" = 0 then 0 else "sales_fact_1997"."store_sales" end)
|
326
|
+
</SQL>
|
327
|
+
<SQL dialect="generic">
|
328
|
+
(case when sales_fact_1997.promotion_id = 0 then 0 else sales_fact_1997.store_sales end)
|
329
|
+
</SQL>
|
330
|
+
</MeasureExpression>
|
331
|
+
</Measure>
|
332
|
+
<CalculatedMember
|
333
|
+
name="Profit"
|
334
|
+
dimension="Measures">
|
335
|
+
<Formula>[Measures].[Store Sales] - [Measures].[Store Cost]</Formula>
|
336
|
+
<CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
|
337
|
+
</CalculatedMember>
|
338
|
+
<CalculatedMember
|
339
|
+
name="Profit last Period"
|
340
|
+
dimension="Measures"
|
341
|
+
formula="COALESCEEMPTY((Measures.[Profit], [Time].[Time].PREVMEMBER), Measures.[Profit])"
|
342
|
+
visible="false">
|
343
|
+
<CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
|
344
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="18"/>
|
345
|
+
</CalculatedMember>
|
346
|
+
<CalculatedMember
|
347
|
+
name="Profit Growth"
|
348
|
+
dimension="Measures"
|
349
|
+
formula="([Measures].[Profit] - [Measures].[Profit last Period]) / [Measures].[Profit last Period]"
|
350
|
+
visible="true"
|
351
|
+
caption="Gewinn-Wachstum">
|
352
|
+
<CalculatedMemberProperty name="FORMAT_STRING" value="0.0%"/>
|
353
|
+
</CalculatedMember>
|
354
|
+
</Cube>
|
355
|
+
|
356
|
+
<Cube name="Warehouse">
|
357
|
+
<Table name="inventory_fact_1997"/>
|
358
|
+
|
359
|
+
<DimensionUsage name="Store" source="Store" foreignKey="store_id"/>
|
360
|
+
<DimensionUsage name="Store Size in SQFT" source="Store Size in SQFT"
|
361
|
+
foreignKey="store_id"/>
|
362
|
+
<DimensionUsage name="Store Type" source="Store Type" foreignKey="store_id"/>
|
363
|
+
<DimensionUsage name="Time" source="Time" foreignKey="time_id"/>
|
364
|
+
<DimensionUsage name="Product" source="Product" foreignKey="product_id"/>
|
365
|
+
<DimensionUsage name="Warehouse" source="Warehouse" foreignKey="warehouse_id"/>
|
366
|
+
|
367
|
+
<Measure name="Store Invoice" column="store_invoice" aggregator="sum"/>
|
368
|
+
<Measure name="Supply Time" column="supply_time" aggregator="sum"/>
|
369
|
+
<Measure name="Warehouse Cost" column="warehouse_cost" aggregator="sum"/>
|
370
|
+
<Measure name="Warehouse Sales" column="warehouse_sales" aggregator="sum"/>
|
371
|
+
<Measure name="Units Shipped" column="units_shipped" aggregator="sum" formatString="#.0"/>
|
372
|
+
<Measure name="Units Ordered" column="units_ordered" aggregator="sum" formatString="#.0"/>
|
373
|
+
<Measure name="Warehouse Profit" aggregator="sum">
|
374
|
+
<MeasureExpression>
|
375
|
+
<SQL dialect="mysql">
|
376
|
+
`warehouse_sales` - `inventory_fact_1997`.`warehouse_cost`
|
377
|
+
</SQL>
|
378
|
+
<SQL dialect="infobright">
|
379
|
+
`warehouse_sales` - `inventory_fact_1997`.`warehouse_cost`
|
380
|
+
</SQL>
|
381
|
+
<SQL dialect="generic">
|
382
|
+
"warehouse_sales" - "inventory_fact_1997"."warehouse_cost"
|
383
|
+
</SQL>
|
384
|
+
</MeasureExpression>
|
385
|
+
</Measure>
|
386
|
+
<CalculatedMember
|
387
|
+
name="Average Warehouse Sale"
|
388
|
+
dimension="Measures">
|
389
|
+
<Formula>[Measures].[Warehouse Sales] / [Measures].[Warehouse Cost]</Formula>
|
390
|
+
<CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
|
391
|
+
</CalculatedMember>
|
392
|
+
<NamedSet name="Top Sellers">
|
393
|
+
<Formula>TopCount([Warehouse].[Warehouse Name].MEMBERS, 5, [Measures].[Warehouse Sales])</Formula>
|
394
|
+
</NamedSet>
|
395
|
+
</Cube>
|
396
|
+
|
397
|
+
<!-- Test a cube based upon a single table. -->
|
398
|
+
<Cube name="Store">
|
399
|
+
<Table name="store"/>
|
400
|
+
<!-- We could have used the shared dimension "Store Type", but we
|
401
|
+
want to test private dimensions without primary key. -->
|
402
|
+
<Dimension name="Store Type">
|
403
|
+
<Hierarchy hasAll="true">
|
404
|
+
<Level name="Store Type" column="store_type" uniqueMembers="true"/>
|
405
|
+
</Hierarchy>
|
406
|
+
</Dimension>
|
407
|
+
|
408
|
+
<!-- We don't have to specify primary key or foreign key since the shared
|
409
|
+
dimension "Store" has the same underlying table as the cube. -->
|
410
|
+
<DimensionUsage name="Store" source="Store"/>
|
411
|
+
|
412
|
+
<Dimension name="Has coffee bar">
|
413
|
+
<Hierarchy hasAll="true">
|
414
|
+
<Level name="Has coffee bar" column="coffee_bar" uniqueMembers="true"
|
415
|
+
type="Boolean"/>
|
416
|
+
</Hierarchy>
|
417
|
+
</Dimension>
|
418
|
+
|
419
|
+
<Measure name="Store Sqft" column="store_sqft" aggregator="sum"
|
420
|
+
formatString="#,###"/>
|
421
|
+
<Measure name="Grocery Sqft" column="grocery_sqft" aggregator="sum"
|
422
|
+
formatString="#,###"/>
|
423
|
+
|
424
|
+
</Cube>
|
425
|
+
|
426
|
+
<Cube name="HR">
|
427
|
+
<Table name="salary"/>
|
428
|
+
<!-- Use private "Time" dimension because key is different than public
|
429
|
+
"Time" dimension. -->
|
430
|
+
<Dimension name="Time" type="TimeDimension" foreignKey="pay_date">
|
431
|
+
<Hierarchy hasAll="false" primaryKey="the_date">
|
432
|
+
<Table name="time_by_day"/>
|
433
|
+
<Level name="Year" column="the_year" type="Numeric" uniqueMembers="true"
|
434
|
+
levelType="TimeYears"/>
|
435
|
+
<Level name="Quarter" column="quarter" uniqueMembers="false"
|
436
|
+
levelType="TimeQuarters"/>
|
437
|
+
<!-- Use the_month as source for the name, so members look like
|
438
|
+
[Time].[1997].[Q1].[Jan] rather than [Time].[1997].[Q1].[1]. -->
|
439
|
+
<Level name="Month" column="month_of_year" nameColumn="the_month"
|
440
|
+
uniqueMembers="false" type="Numeric" levelType="TimeMonths"/>
|
441
|
+
</Hierarchy>
|
442
|
+
</Dimension>
|
443
|
+
|
444
|
+
<Dimension name="Store" foreignKey="employee_id" >
|
445
|
+
<Hierarchy hasAll="true" primaryKey="employee_id"
|
446
|
+
primaryKeyTable="employee">
|
447
|
+
<Join leftKey="store_id" rightKey="store_id">
|
448
|
+
<Table name="employee"/>
|
449
|
+
<Table name="store"/>
|
450
|
+
</Join>
|
451
|
+
<Level name="Store Country" table="store" column="store_country"
|
452
|
+
uniqueMembers="true"/>
|
453
|
+
<Level name="Store State" table="store" column="store_state"
|
454
|
+
uniqueMembers="true"/>
|
455
|
+
<Level name="Store City" table="store" column="store_city"
|
456
|
+
uniqueMembers="false"/>
|
457
|
+
<Level name="Store Name" table="store" column="store_name"
|
458
|
+
uniqueMembers="true">
|
459
|
+
<Property name="Store Type" column="store_type"/>
|
460
|
+
<Property name="Store Manager" column="store_manager"/>
|
461
|
+
<Property name="Store Sqft" column="store_sqft" type="Numeric"/>
|
462
|
+
<Property name="Grocery Sqft" column="grocery_sqft" type="Numeric"/>
|
463
|
+
<Property name="Frozen Sqft" column="frozen_sqft" type="Numeric"/>
|
464
|
+
<Property name="Meat Sqft" column="meat_sqft" type="Numeric"/>
|
465
|
+
<Property name="Has coffee bar" column="coffee_bar" type="Boolean"/>
|
466
|
+
<Property name="Street address" column="store_street_address"
|
467
|
+
type="String"/>
|
468
|
+
</Level>
|
469
|
+
</Hierarchy>
|
470
|
+
</Dimension>
|
471
|
+
|
472
|
+
<Dimension name="Pay Type" foreignKey="employee_id">
|
473
|
+
<Hierarchy hasAll="true" primaryKey="employee_id"
|
474
|
+
primaryKeyTable="employee">
|
475
|
+
<Join leftKey="position_id" rightKey="position_id">
|
476
|
+
<Table name="employee"/>
|
477
|
+
<Table name="position"/>
|
478
|
+
</Join>
|
479
|
+
<Level name="Pay Type" table="position" column="pay_type"
|
480
|
+
uniqueMembers="true"/>
|
481
|
+
</Hierarchy>
|
482
|
+
</Dimension>
|
483
|
+
|
484
|
+
<Dimension name="Store Type" foreignKey="employee_id">
|
485
|
+
<Hierarchy hasAll="true" primaryKeyTable="employee" primaryKey="employee_id">
|
486
|
+
<Join leftKey="store_id" rightKey="store_id">
|
487
|
+
<Table name="employee"/>
|
488
|
+
<Table name="store"/>
|
489
|
+
</Join>
|
490
|
+
<Level name="Store Type" table="store" column="store_type"
|
491
|
+
uniqueMembers="true"/>
|
492
|
+
</Hierarchy>
|
493
|
+
</Dimension>
|
494
|
+
|
495
|
+
<Dimension name="Position" foreignKey="employee_id">
|
496
|
+
<Hierarchy hasAll="true" allMemberName="All Position"
|
497
|
+
primaryKey="employee_id">
|
498
|
+
<Table name="employee"/>
|
499
|
+
<Level name="Management Role" uniqueMembers="true"
|
500
|
+
column="management_role"/>
|
501
|
+
<Level name="Position Title" uniqueMembers="false"
|
502
|
+
column="position_title" ordinalColumn="position_id"/>
|
503
|
+
</Hierarchy>
|
504
|
+
</Dimension>
|
505
|
+
|
506
|
+
<Dimension name="Department" foreignKey="department_id">
|
507
|
+
<Hierarchy hasAll="true" primaryKey="department_id">
|
508
|
+
<Table name="department"/>
|
509
|
+
<Level name="Department Description" type="Numeric" uniqueMembers="true"
|
510
|
+
column="department_id"/>
|
511
|
+
</Hierarchy>
|
512
|
+
</Dimension>
|
513
|
+
<Dimension name="Employees" foreignKey="employee_id">
|
514
|
+
<Hierarchy hasAll="true" allMemberName="All Employees"
|
515
|
+
primaryKey="employee_id">
|
516
|
+
<Table name="employee"/>
|
517
|
+
<Level name="Employee Id" type="Numeric" uniqueMembers="true"
|
518
|
+
column="employee_id" parentColumn="supervisor_id"
|
519
|
+
nameColumn="full_name" nullParentValue="0">
|
520
|
+
<Closure parentColumn="supervisor_id" childColumn="employee_id">
|
521
|
+
<Table name="employee_closure"/>
|
522
|
+
</Closure>
|
523
|
+
<Property name="Marital Status" column="marital_status"/>
|
524
|
+
<Property name="Position Title" column="position_title"/>
|
525
|
+
<Property name="Gender" column="gender"/>
|
526
|
+
<Property name="Salary" column="salary"/>
|
527
|
+
<Property name="Education Level" column="education_level"/>
|
528
|
+
<Property name="Management Role" column="management_role"/>
|
529
|
+
</Level>
|
530
|
+
</Hierarchy>
|
531
|
+
</Dimension>
|
532
|
+
|
533
|
+
<Measure name="Org Salary" column="salary_paid" aggregator="sum"
|
534
|
+
formatString="Currency"/>
|
535
|
+
<Measure name="Count" column="employee_id" aggregator="count"
|
536
|
+
formatString="#,#"/>
|
537
|
+
<Measure name="Number of Employees" column="employee_id"
|
538
|
+
aggregator="distinct-count" formatString="#,#"/>
|
539
|
+
<CalculatedMember name="Employee Salary" dimension="Measures"
|
540
|
+
formatString="Currency"
|
541
|
+
formula="([Employees].currentmember.datamember, [Measures].[Org Salary])"/>
|
542
|
+
<CalculatedMember name="Avg Salary" dimension="Measures"
|
543
|
+
formatString="Currency"
|
544
|
+
formula="[Measures].[Org Salary]/[Measures].[Number of Employees]"/>
|
545
|
+
</Cube>
|
546
|
+
|
547
|
+
<!-- Cube with one ragged hierarchy (otherwise the same as the "Sales"
|
548
|
+
cube). -->
|
549
|
+
<Cube name="Sales Ragged">
|
550
|
+
<Table name="sales_fact_1997">
|
551
|
+
<AggExclude name="agg_pc_10_sales_fact_1997"/>
|
552
|
+
<AggExclude name="agg_lc_10_sales_fact_1997"/>
|
553
|
+
</Table>
|
554
|
+
<Dimension name="Store" foreignKey="store_id">
|
555
|
+
<Hierarchy hasAll="true" primaryKey="store_id">
|
556
|
+
<Table name="store_ragged"/>
|
557
|
+
<Level name="Store Country" column="store_country" uniqueMembers="true"
|
558
|
+
hideMemberIf="Never"/>
|
559
|
+
<Level name="Store State" column="store_state" uniqueMembers="true"
|
560
|
+
hideMemberIf="IfParentsName"/>
|
561
|
+
<Level name="Store City" column="store_city" uniqueMembers="false"
|
562
|
+
hideMemberIf="IfBlankName"/>
|
563
|
+
<Level name="Store Name" column="store_name" uniqueMembers="true"
|
564
|
+
hideMemberIf="Never">
|
565
|
+
<Property name="Store Type" column="store_type"/>
|
566
|
+
<Property name="Store Manager" column="store_manager"/>
|
567
|
+
<Property name="Store Sqft" column="store_sqft" type="Numeric"/>
|
568
|
+
<Property name="Grocery Sqft" column="grocery_sqft" type="Numeric"/>
|
569
|
+
<Property name="Frozen Sqft" column="frozen_sqft" type="Numeric"/>
|
570
|
+
<Property name="Meat Sqft" column="meat_sqft" type="Numeric"/>
|
571
|
+
<Property name="Has coffee bar" column="coffee_bar" type="Boolean"/>
|
572
|
+
<Property name="Street address" column="store_street_address" type="String"/>
|
573
|
+
</Level>
|
574
|
+
</Hierarchy>
|
575
|
+
</Dimension>
|
576
|
+
|
577
|
+
<Dimension name="Geography" foreignKey="store_id">
|
578
|
+
<Hierarchy hasAll="true" primaryKey="store_id">
|
579
|
+
<Table name="store_ragged"/>
|
580
|
+
<Level name="Country" column="store_country" uniqueMembers="true"
|
581
|
+
hideMemberIf="Never"/>
|
582
|
+
<Level name="State" column="store_state" uniqueMembers="true"
|
583
|
+
hideMemberIf="IfParentsName"/>
|
584
|
+
<Level name="City" column="store_city" uniqueMembers="false"
|
585
|
+
hideMemberIf="IfBlankName"/>
|
586
|
+
</Hierarchy>
|
587
|
+
</Dimension>
|
588
|
+
|
589
|
+
<DimensionUsage name="Store Size in SQFT" source="Store Size in SQFT"
|
590
|
+
foreignKey="store_id"/>
|
591
|
+
<DimensionUsage name="Store Type" source="Store Type" foreignKey="store_id"/>
|
592
|
+
<DimensionUsage name="Time" source="Time" foreignKey="time_id"/>
|
593
|
+
<DimensionUsage name="Product" source="Product" foreignKey="product_id"/>
|
594
|
+
<Dimension name="Promotion Media" foreignKey="promotion_id">
|
595
|
+
<Hierarchy hasAll="true" allMemberName="All Media" primaryKey="promotion_id">
|
596
|
+
<Table name="promotion"/>
|
597
|
+
<Level name="Media Type" column="media_type" uniqueMembers="true"/>
|
598
|
+
</Hierarchy>
|
599
|
+
</Dimension>
|
600
|
+
<Dimension name="Promotions" foreignKey="promotion_id">
|
601
|
+
<Hierarchy hasAll="true" allMemberName="All Promotions" primaryKey="promotion_id">
|
602
|
+
<Table name="promotion"/>
|
603
|
+
<Level name="Promotion Name" column="promotion_name" uniqueMembers="true"/>
|
604
|
+
</Hierarchy>
|
605
|
+
</Dimension>
|
606
|
+
<Dimension name="Customers" foreignKey="customer_id">
|
607
|
+
<Hierarchy hasAll="true" allMemberName="All Customers" primaryKey="customer_id">
|
608
|
+
<Table name="customer"/>
|
609
|
+
<Level name="Country" column="country" uniqueMembers="true"/>
|
610
|
+
<Level name="State Province" column="state_province" uniqueMembers="true"/>
|
611
|
+
<Level name="City" column="city" uniqueMembers="false"/>
|
612
|
+
<Level name="Name" uniqueMembers="true">
|
613
|
+
<KeyExpression>
|
614
|
+
<SQL dialect="oracle">
|
615
|
+
"fname" || ' ' || "lname"
|
616
|
+
</SQL>
|
617
|
+
<SQL dialect="hsqldb">
|
618
|
+
"fname" || ' ' || "lname"
|
619
|
+
</SQL>
|
620
|
+
<SQL dialect="access">
|
621
|
+
fname + ' ' + lname
|
622
|
+
</SQL>
|
623
|
+
<SQL dialect="postgres">
|
624
|
+
"fname" || ' ' || "lname"
|
625
|
+
</SQL>
|
626
|
+
<SQL dialect="mysql">
|
627
|
+
CONCAT(`customer`.`fname`, ' ', `customer`.`lname`)
|
628
|
+
</SQL>
|
629
|
+
<SQL dialect="mssql">
|
630
|
+
fname + ' ' + lname
|
631
|
+
</SQL>
|
632
|
+
<SQL dialect="derby">
|
633
|
+
"customer"."fullname"
|
634
|
+
</SQL>
|
635
|
+
<SQL dialect="db2">
|
636
|
+
CONCAT(CONCAT("customer"."fname", ' '), "customer"."lname")
|
637
|
+
</SQL>
|
638
|
+
<SQL dialect="luciddb">
|
639
|
+
"fname" || ' ' || "lname"
|
640
|
+
</SQL>
|
641
|
+
<SQL dialect="neoview">
|
642
|
+
"customer"."fullname"
|
643
|
+
</SQL>
|
644
|
+
<SQL dialect="generic">
|
645
|
+
fullname
|
646
|
+
</SQL>
|
647
|
+
</KeyExpression>
|
648
|
+
<Property name="Gender" column="gender"/>
|
649
|
+
<Property name="Marital Status" column="marital_status"/>
|
650
|
+
<Property name="Education" column="education"/>
|
651
|
+
<Property name="Yearly Income" column="yearly_income"/>
|
652
|
+
</Level>
|
653
|
+
</Hierarchy>
|
654
|
+
</Dimension>
|
655
|
+
<Dimension name="Education Level" foreignKey="customer_id">
|
656
|
+
<Hierarchy hasAll="true" primaryKey="customer_id">
|
657
|
+
<Table name="customer"/>
|
658
|
+
<Level name="Education Level" column="education" uniqueMembers="true"/>
|
659
|
+
</Hierarchy>
|
660
|
+
</Dimension>
|
661
|
+
<Dimension name="Gender" foreignKey="customer_id">
|
662
|
+
<Hierarchy hasAll="true" allMemberName="All Gender" primaryKey="customer_id">
|
663
|
+
<Table name="customer"/>
|
664
|
+
<Level name="Gender" column="gender" uniqueMembers="true"/>
|
665
|
+
</Hierarchy>
|
666
|
+
</Dimension>
|
667
|
+
<Dimension name="Marital Status" foreignKey="customer_id">
|
668
|
+
<Hierarchy hasAll="true" allMemberName="All Marital Status" primaryKey="customer_id">
|
669
|
+
<Table name="customer"/>
|
670
|
+
<Level name="Marital Status" column="marital_status" uniqueMembers="true"/>
|
671
|
+
</Hierarchy>
|
672
|
+
</Dimension>
|
673
|
+
<Dimension name="Yearly Income" foreignKey="customer_id">
|
674
|
+
<Hierarchy hasAll="true" primaryKey="customer_id">
|
675
|
+
<Table name="customer"/>
|
676
|
+
<Level name="Yearly Income" column="yearly_income" uniqueMembers="true"/>
|
677
|
+
</Hierarchy>
|
678
|
+
</Dimension>
|
679
|
+
<Measure name="Unit Sales" column="unit_sales" aggregator="sum"
|
680
|
+
formatString="Standard"/>
|
681
|
+
<Measure name="Store Cost" column="store_cost" aggregator="sum"
|
682
|
+
formatString="#,###.00"/>
|
683
|
+
<Measure name="Store Sales" column="store_sales" aggregator="sum"
|
684
|
+
formatString="#,###.00"/>
|
685
|
+
<Measure name="Sales Count" column="product_id" aggregator="count"
|
686
|
+
formatString="#,###"/>
|
687
|
+
<Measure name="Customer Count" column="customer_id" aggregator="distinct-count"
|
688
|
+
formatString="#,###"/>
|
689
|
+
</Cube>
|
690
|
+
|
691
|
+
<!-- a simpler version of "Sales" (with MEMBER_ORDINAL-properties) -->
|
692
|
+
<Cube name="Sales 2">
|
693
|
+
<Table name="sales_fact_1997"/>
|
694
|
+
|
695
|
+
<DimensionUsage name="Time" source="Time" foreignKey="time_id"/>
|
696
|
+
<DimensionUsage name="Product" source="Product" foreignKey="product_id"/>
|
697
|
+
|
698
|
+
<Dimension name="Gender" foreignKey="customer_id">
|
699
|
+
<Hierarchy hasAll="true" allMemberName="All Gender" primaryKey="customer_id">
|
700
|
+
<Table name="customer"/>
|
701
|
+
<Level name="Gender" column="gender" uniqueMembers="true"/>
|
702
|
+
</Hierarchy>
|
703
|
+
</Dimension>
|
704
|
+
|
705
|
+
<Measure name="Sales Count" column="product_id" aggregator="count" formatString="#,###">
|
706
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="1"/>
|
707
|
+
</Measure>
|
708
|
+
|
709
|
+
<Measure name="Unit Sales" column="unit_sales" aggregator="sum" formatString="Standard">
|
710
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="2"/>
|
711
|
+
</Measure>
|
712
|
+
|
713
|
+
<Measure name="Store Sales" column="store_sales" aggregator="sum" formatString="#,###.00">
|
714
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="3"/>
|
715
|
+
</Measure>
|
716
|
+
|
717
|
+
<Measure name="Store Cost" column="store_cost" aggregator="sum" formatString="#,###.00">
|
718
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="6"/>
|
719
|
+
</Measure>
|
720
|
+
|
721
|
+
<Measure name="Customer Count" column="customer_id" aggregator="distinct-count" formatString="#,###">
|
722
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="7"/>
|
723
|
+
</Measure>
|
724
|
+
|
725
|
+
<CalculatedMember
|
726
|
+
name="Profit"
|
727
|
+
dimension="Measures">
|
728
|
+
<Formula>[Measures].[Store Sales] - [Measures].[Store Cost]</Formula>
|
729
|
+
<CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
|
730
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="4"/>
|
731
|
+
</CalculatedMember>
|
732
|
+
|
733
|
+
<CalculatedMember
|
734
|
+
name="Profit last Period"
|
735
|
+
dimension="Measures"
|
736
|
+
formula="COALESCEEMPTY((Measures.[Profit], [Time].[Time].PREVMEMBER), Measures.[Profit])"
|
737
|
+
visible="false">
|
738
|
+
<CalculatedMemberProperty name="MEMBER_ORDINAL" value="5"/>
|
739
|
+
</CalculatedMember>
|
740
|
+
</Cube>
|
741
|
+
|
742
|
+
<VirtualCube name="Warehouse and Sales" defaultMeasure="Store Sales">
|
743
|
+
<VirtualCubeDimension cubeName="Sales" name="Customers"/>
|
744
|
+
<VirtualCubeDimension cubeName="Sales" name="Education Level"/>
|
745
|
+
<VirtualCubeDimension cubeName="Sales" name="Gender"/>
|
746
|
+
<VirtualCubeDimension cubeName="Sales" name="Marital Status"/>
|
747
|
+
<VirtualCubeDimension name="Product"/>
|
748
|
+
<VirtualCubeDimension cubeName="Sales" name="Promotion Media"/>
|
749
|
+
<VirtualCubeDimension cubeName="Sales" name="Promotions"/>
|
750
|
+
<VirtualCubeDimension name="Store"/>
|
751
|
+
<VirtualCubeDimension name="Time"/>
|
752
|
+
<VirtualCubeDimension cubeName="Sales" name="Yearly Income"/>
|
753
|
+
<VirtualCubeDimension cubeName="Warehouse" name="Warehouse"/>
|
754
|
+
<VirtualCubeMeasure cubeName="Sales" name="[Measures].[Sales Count]"/>
|
755
|
+
<VirtualCubeMeasure cubeName="Sales" name="[Measures].[Store Cost]"/>
|
756
|
+
<VirtualCubeMeasure cubeName="Sales" name="[Measures].[Store Sales]"/>
|
757
|
+
<VirtualCubeMeasure cubeName="Sales" name="[Measures].[Unit Sales]"/>
|
758
|
+
<VirtualCubeMeasure cubeName="Sales" name="[Measures].[Profit]"/>
|
759
|
+
<VirtualCubeMeasure cubeName="Sales" name="[Measures].[Profit Growth]"/>
|
760
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Store Invoice]"/>
|
761
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Supply Time]"/>
|
762
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Units Ordered]"/>
|
763
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Units Shipped]"/>
|
764
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Warehouse Cost]"/>
|
765
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Warehouse Profit]"/>
|
766
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Warehouse Sales]"/>
|
767
|
+
<VirtualCubeMeasure cubeName="Warehouse" name="[Measures].[Average Warehouse Sale]"/>
|
768
|
+
<!--
|
769
|
+
<VirtualCubeMeasure cubeName="Sales" name="[Measures].[Store Sales Net]"/>
|
770
|
+
-->
|
771
|
+
<CalculatedMember name="Profit Per Unit Shipped" dimension="Measures">
|
772
|
+
<Formula>[Measures].[Profit] / [Measures].[Units Shipped]</Formula>
|
773
|
+
</CalculatedMember>
|
774
|
+
</VirtualCube>
|
775
|
+
|
776
|
+
<!-- A California manager can only see customers and stores in California.
|
777
|
+
They cannot drill down on Gender. -->
|
778
|
+
<Role name="California manager">
|
779
|
+
<SchemaGrant access="none">
|
780
|
+
<CubeGrant cube="Sales" access="all">
|
781
|
+
<HierarchyGrant hierarchy="[Store]" access="custom"
|
782
|
+
topLevel="[Store].[Store Country]">
|
783
|
+
<MemberGrant member="[Store].[USA].[CA]" access="all"/>
|
784
|
+
<MemberGrant member="[Store].[USA].[CA].[Los Angeles]" access="none"/>
|
785
|
+
</HierarchyGrant>
|
786
|
+
<HierarchyGrant hierarchy="[Customers]" access="custom"
|
787
|
+
topLevel="[Customers].[State Province]" bottomLevel="[Customers].[City]">
|
788
|
+
<MemberGrant member="[Customers].[USA].[CA]" access="all"/>
|
789
|
+
<MemberGrant member="[Customers].[USA].[CA].[Los Angeles]" access="none"/>
|
790
|
+
</HierarchyGrant>
|
791
|
+
<HierarchyGrant hierarchy="[Gender]" access="none"/>
|
792
|
+
</CubeGrant>
|
793
|
+
</SchemaGrant>
|
794
|
+
</Role>
|
795
|
+
|
796
|
+
<Role name="No HR Cube">
|
797
|
+
<SchemaGrant access="all">
|
798
|
+
<CubeGrant cube="HR" access="none"/>
|
799
|
+
</SchemaGrant>
|
800
|
+
</Role>
|
801
|
+
|
802
|
+
</Schema>
|