diff --git a/config/ci_test.yaml.example b/config/ci_test.yaml.example
index f9f7ef30ae975a84dd924a0eb956b51fd2a001bd..7389688eb676dcfeb408f77badba2b485c76f2aa 100644
--- a/config/ci_test.yaml.example
+++ b/config/ci_test.yaml.example
@@ -25,6 +25,7 @@ schema:
                 - "met:0"
                 - "met:1"
                 - "met:2"
+                - "met:10"
         -
             alias: "View 1"
             data: "test/postgres/fixtures/view1.json"
@@ -44,6 +45,7 @@ schema:
             metrics:
                 - "met:5"
                 - "met:6"
+                - "met:11"
         -
             alias: "View 3"
             data: "test/postgres/fixtures/view3.json"
@@ -93,8 +95,6 @@ schema:
                 - "dim:6"
             metrics:
                 - "met:9"
-                - "met:10"
-                - "met:11"
         -
             alias: "view 9"
             data: "test/postgres/fixtures/view9.json"
diff --git a/src/adapter/postgres.spec.ts b/src/adapter/postgres.spec.ts
index 4db633886ffb6250f8f64d1c278d2d96e1044878..70ab8478fe58c925df0a58714b09365d1b27a8e3 100644
--- a/src/adapter/postgres.spec.ts
+++ b/src/adapter/postgres.spec.ts
@@ -319,4 +319,42 @@ describe("postgres adapter", () => {
             done();
         });
     });
+
+    it("should get data from a unmaterializeble view", (done) => {
+        let view = adapterScenario.unMaterializebleView;
+        adapter.getDataFromView(view, (err, result) => {
+            expect(err).to.be.a("null");
+            expect(result).to.be.an("array");
+            expect(result).to.have.length(5);
+            expect(result[0]).to.be.an("object");
+            let keys: string[] = [];
+            keys = keys.concat(view.metrics.map((item) => item.name));
+            keys = keys.concat(view.dimensions.map((item) => item.name));
+            result.forEach((row) => {
+                expect(row).to.be.an("object");
+                expect(row).to.have.all.keys(keys);
+            });
+
+            done();
+        });
+    });
+
+    it("should get data from partial joins", (done) => {
+        let view = adapterScenario.partialJoinView;
+        adapter.getDataFromView(view, (err, result) => {
+            expect(err).to.be.a("null");
+            expect(result).to.be.an("array");
+            expect(result).to.have.length(5);
+            expect(result[0]).to.be.an("object");
+            let keys: string[] = [];
+            keys = keys.concat(view.metrics.map((item) => item.name));
+            keys = keys.concat(view.dimensions.map((item) => item.name));
+            result.forEach((row) => {
+                expect(row).to.be.an("object");
+                expect(row).to.have.all.keys(keys);
+            });
+
+            done();
+        });
+    });
 });
diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts
index 9035c3746729fbe94a4652618103d43980d626d5..b1e44806b3ac8eed7864872f0845c0302e4b76cc 100644
--- a/src/adapter/postgres.ts
+++ b/src/adapter/postgres.ts
@@ -27,9 +27,25 @@ import { AggregationType, RelationType } from "../common/types";
 import { View } from "../core/view";
 import { Pool, PoolConfig } from "pg";
 
+interface ExpandedView {
+    dimensions: Dimension[];
+    metrics: Metric[];
+    dimMetrics: Metric[];
+    keys: Dimension[];
+    clauses: Clause[];
+    from: string;
+    id: string;
+    origin: boolean;
+}
+
 interface DimInfo {
     dim: Dimension;
-    views: View[];
+    views: ExpandedView[];
+}
+
+interface DimTranslation {
+    aliased: string;
+    noalias: string;
 }
 
 export class PostgresAdapter extends Adapter {
@@ -60,18 +76,422 @@ export class PostgresAdapter extends Adapter {
     }
 
     public getQueryFromView(view: View): string {
+        /*
+            Find the base (materialized) views that has this data and exapand
+            than (make a parse to the format used in the adapter)
+        */
         const materialized = this.searchMaterializedViews(view).sort((a, b) => {
             return (a.id < b.id) ? -1 : 1;
+        }).map((item) => {
+            return {
+                id: item.id,
+                from: "view_" + item.id,
+                dimMetrics: [],
+                metrics: item.metrics.filter((i) => {
+                    return view.metrics.some((j) => i.name === j.name);
+                }),
+                dimensions: item.dimensions,
+                keys: item.keys,
+                clauses: item.clauses,
+                origin: item.origin
+            };
         });
 
-        const unique = [materialized[0]];
+        // Remove repeated views from the result
+        let partialJoin = [materialized[0]];
         for (let i = 1; i < materialized.length; ++i) {
             if (materialized[i - 1].id !== materialized[i].id) {
-                unique.push(materialized[i]);
+                partialJoin.push(materialized[i]);
             }
         }
 
-        return this.buildQuery(view, unique);
+        /*
+            If there is more than one source of data (tables/views)
+            a join is needed.
+
+            Partial Join represents how many sources still exists,
+            every join reduces this number.
+        */
+        while (partialJoin.length > 1) {
+            /*
+                Variable map finds what dimenensions are still needed to
+                complete this query, they are required for 2 reasons.
+                1 - To make joins
+                2 - Because they are in the query
+
+                For each view that has this dimension we add one score to
+                this dimension, if they are in the query the same.
+
+                Automatically if the dimension is in the query there will be
+                at least one view with this atribute (or the query could not be
+                completed) so dimensions in the query always have score of
+                at least 2.
+
+                To make a join the dimension must be in 2 different views,
+                creating a score of 2 either.
+
+                If the score is less than 2 so this dimension is not required
+                anymore and can be removed.
+            */
+            let map: { [key: string]: number } = {};
+            let partialsChange = false;
+            for (let i = 0; i < partialJoin.length; ++i) {
+                const dims = partialJoin[i].dimensions;
+                for (let k = 0; k < dims.length; ++k) {
+                    if (!map[dims[k].name])  {
+                        map[dims[k].name] = 1;
+                    }
+
+                    else {
+                        ++map[dims[k].name];
+                    }
+                }
+            }
+
+            for (let i = 0; i < view.dimensions.length; ++i) {
+                let dim = view.dimensions[i];
+                while (dim !== null) {
+                    if (map[dim.name])  {
+                        ++map[dim.name];
+                    }
+                    dim = dim.parent;
+                }
+            }
+
+            for (let i = 0; i < partialJoin.length; ++i) {
+                const dims = partialJoin[i].dimensions.filter((item) => {
+                    return map[item.name] > 1;
+                });
+                const keys = partialJoin[i].keys.filter((item) => {
+                    return map[item.name] > 1;
+                });
+                /*
+                    At this point the dimensions with less than score 2
+                    are removed, if this happens the view is agreggated
+                    again, with less dimensions, removing this dimension
+                    from the view.
+                */
+                if (dims.length  < partialJoin[i].dimensions.length) {
+                    const partial = new View({
+                        metrics: partialJoin[i].metrics,
+                        dimensions: dims,
+                        keys: keys,
+                        origin: false,
+                        clauses: partialJoin[i].clauses,
+                        materialized: false
+                    });
+                    const from  = "(" +
+                                   this.buildQuery(partial, [partialJoin[i]]) +
+                                   ") AS view_" + partial.id + "\n";
+
+                    partialJoin[i].id = partial.id;
+                    partialJoin[i].dimensions = partial.dimensions;
+                    partialJoin[i].keys = partial.keys;
+                    partialJoin[i].origin = partial.origin;
+                    partialJoin[i].from = from;
+
+                    partialsChange = true;
+                }
+            }
+            /*
+                If at least one of the views changed (have the number of
+                dimensions reduced) returns to the begining of the loop
+                again.
+
+                Othewise we need to make a join.
+            */
+            if (!partialsChange) {
+                /*
+                    Sorting the views by keys.
+                    If the keys are identical, then they
+                    will be in sequence, and views with identical
+                    keys can be joined.
+
+                    Sort an array of keys is the same as sort a
+                    array of strings.
+                */
+                const sorted = partialJoin.sort((a, b) => {
+                    return this.compareKeys(a.keys, b.keys);
+                });
+                /*
+                    First of all, the remaining views are splited in segments.
+
+                    A segment contains views with the same keys that are great
+                    to make joins. Joins like this do not create "dimensional
+                    metrics".
+
+                    In joins like this one row of each view will  be connected
+                    with at most one row of each other table.
+                */
+                const segment = [[sorted[0]]];
+                let segmentId = 0;
+                for (let i = 1; i < sorted.length; ++i) {
+                    if (this.compareKeys(sorted[i - 1].keys, sorted[i].keys) === 0) {
+                        segment[segmentId].push(sorted[i]);
+                    }
+                    else {
+                        ++segmentId;
+                        segment.push([sorted[i]]);
+                    }
+                }
+
+                partialJoin = [];
+                let ableToJoin = false;
+
+                for (let i = 0; i < segment.length; ++i) {
+                    /*
+                        If a segment has more than one view, a join can be made
+                    */
+                    if (segment[i].length > 1) {
+                        let mets: Metric[] = [];
+                        let clauses: Clause[] = [];
+                        let dims: Dimension[] = [];
+                        let dimMetrics: Metric[] = [];
+                        for (let j = 0; j < segment[i].length; ++j) {
+                            mets = mets.concat(segment[i][j].metrics);
+                            clauses = clauses.concat(segment[i][j].clauses);
+                            dims = dims.concat(segment[i][j].dimensions);
+                            dimMetrics = dimMetrics.concat(segment[i][j].dimMetrics);
+                        }
+
+                        dims = this.removeDuplicatedDimensions(dims);
+                        /*
+                            Its atributes are just concatenated and the
+                            duplicates removed.
+                        */
+
+                        const partial = new View({
+                            metrics: mets,
+                            dimensions: dims,
+                            keys: segment[i][0].keys,
+                            origin: false,
+                            clauses: clauses,
+                            materialized: false
+                        });
+                        const viewFrom  = "(" +
+                                    this.buildQuery(partial, segment[i]) +
+                                    ") AS view_" + partial.id + "\n";
+
+                        partialJoin.push({
+                            id: partial.id,
+                            from: viewFrom,
+                            dimMetrics: dimMetrics,
+                            metrics: partial.metrics,
+                            dimensions: partial.dimensions,
+                            keys: partial.keys,
+                            clauses: partial.clauses,
+                            origin: partial.origin
+                        });
+
+                        ableToJoin = true;
+                    }
+
+                    else {
+                        /*
+                            If the segment has just one view, anything can be
+                            done at this point, so just reinsert this view in
+                            set of views.
+                        */
+                        partialJoin.push(segment[i][0]);
+                    }
+                }
+
+                /*
+                    If at least one join was made in the last part (a segment
+                    with more than one view) than return to the begining of the
+                    loop.
+
+                    This permits after a join remove the dimensions that were
+                    only choosen to this join, and are no longer required
+
+                    Ideally the joins should be restrict the join method used
+                    above, but in some cases this can not be done.
+
+                    So if all the segments have only one view inside, move
+                    to the next method.
+                */
+                if (!ableToJoin) {
+                    /*
+                        At this point 2 views will be joined, first the
+                        similarity with each pair of views is calculated,
+                        the pair with the biggedt similarity will be joined.
+
+                        Similarity is calculated with the number of common
+                        dimensions in the keys.
+                    */
+                    let similarity = 0;
+                    let idx0 = 0;
+                    let idx1 = 1;
+                    for (let i = 0; i < partialJoin.length; ++i) {
+                        for (let j = i + 1 ; j < partialJoin.length; ++j) {
+                            const pi = partialJoin[i].keys;
+                            const pj = partialJoin[j].keys;
+                            let score = this.similarDimensions (pi, pj);
+                            if (similarity < score) {
+                                similarity = score;
+                                idx0 = i;
+                                idx1 = j;
+                            }
+                        }
+                    }
+
+                    const partial0 = partialJoin[idx0];
+                    const partial1 = partialJoin[idx1];
+
+                    partialJoin.splice(idx1, 1);
+                    partialJoin.splice(idx0, 1);
+
+                    /*
+                        Once the views are select they are joined with the
+                        same method, concatenedted its atributes and
+                        removing duplicates, however the nasty effect of
+                        this join is the creation of "dimensional metrics".
+
+                        "Dimensional metrics" are metrics that can no longer
+                        be aggregated, and at this point to the end
+                        of a query they will act as dimensions.
+
+                        This change happens to avoid inconsistency generated
+                        by a join where one row of one table can be connected
+                        to more than one of other table.
+
+                        Take this example.
+
+                        View0 : metrics [met0], dimensions [dim0]
+                        values: [{met0: 10, dim0: 1}]
+                        View1 : metrics [met1], dimensions [dim2]
+                        values: [{met1: 10, dim2: 1}. {met1: 5, dim2: 2}]
+                        View2 : metrics [], dimensions [dim0, dim1, dim2]
+                        values: [
+                            {dim0: 1, dim1: 1, dim2: 1},
+                            {dim0: 1, dim1: 1, dim2: 2}
+                        ]
+                        The query is metrics [met0, met1] and dimensions [dim1]
+                        First a join of View0 and View1 is made, the result
+                        is: [
+                            {dim0: 1, dim1: 1, dim2: 1, met0: 10},
+                            {dim0: 1, dim1: 1, dim2: 2, met0: 10}
+                        ]
+                        Note that the value of met0 is duplicated.
+                        Now dim0 is removed, than joined with view2 resulting
+                        in: [
+                            {met1: 10, dim1: 1, dim2: 1, met0: 10},
+                            {met1: 5 , dim1: 1, dim2: 2, met0: 10}
+                        ]
+
+                        Lets assume that the agregation is SUM
+                        If we remove dim2 and re-agregate the result is: [
+                            {met1: 15, dim1: 1, met0: 20}
+                        ]
+
+                        This result is wrong. The replication of the value
+                        met0 affects the result.
+
+                        See if met1 was not required, first the dimemnsion would
+                        be reduced, left dim0 and dim1, than joined that reduced
+                        again resulting in the value [
+                            {dim1:1, met0: 10}
+                        ]
+
+                        Is this case there is no duplication and the aggregation
+                        does not include more rows than should.
+
+                        To solve this problem the met0 must become a dimension,
+                        in other words, not aggregated again. If the met0 was
+                        not agregated in the query met0, met1, dim1 the result
+                        is: [
+                            {met1: 15, dim1: 1, met0: 10}
+                        ]
+                        what is compatible.
+
+                        After this extreme long explanation what must be
+                        known is: Joining views with diferent keys
+                        generate "dimensional metrics".
+
+                        Views with "dimensional metrics" can not used for future
+                        queries because can not be re-agregated, so this must be
+                        avoided and is one-query only views.
+                    */
+
+                    let dimMetrics: Metric[];
+                    let mets: Metric[];
+                    let dims = partial0.dimensions.concat(partial1.dimensions);
+                    dims = this.removeDuplicatedDimensions(dims);
+                    let keys = partial0.keys.concat(partial1.keys);
+                    keys = this.removeDuplicatedDimensions(keys);
+                    if (partial0.keys.length === similarity) {
+                        /*
+                            Here the metrics become dimensions, but the effect
+                            can be reduced. If the keys of partial0
+                            is a sub set of the keys ou partial1
+                            than the number of rows of partial 1 is not
+                            affected, in other words the metrics of partial1
+                            can be aggregated and does not need to become
+                            dimensions.
+                        */
+                        partial0.dimMetrics = partial0.dimMetrics.concat(partial0.metrics);
+                        partial0.metrics = [];
+                        mets = partial1.metrics;
+                    }
+
+                    else if (partial1.keys.length === similarity) {
+                        /*
+                            The same occurs if the keys of partia1 is a subset
+                            of partial0.
+                        */
+                        partial1.dimMetrics = partial1.dimMetrics.concat(partial1.metrics);
+                        partial1.metrics = [];
+                        mets = partial0.metrics;
+                    }
+
+                    else {
+                        /*
+                            But if there is no sub set, than both sides have
+                            the metrics turned in dimensions.
+                        */
+                        partial0.dimMetrics = partial0.dimMetrics.concat(partial0.metrics);
+                        partial0.metrics = [];
+                        partial1.dimMetrics = partial1.dimMetrics.concat(partial1.metrics);
+                        partial1.metrics = [];
+                        mets = [];
+                    }
+
+                    dimMetrics = partial0.dimMetrics.concat(partial1.dimMetrics);
+                    const partial = new View({
+                        metrics: mets,
+                        dimensions: dims,
+                        keys: keys,
+                        origin: false,
+                        clauses: partial0.clauses.concat(partial1.clauses),
+                        materialized: false
+                    });
+                    const viewFrom  = "(" +
+                            this.buildQuery(partial, [partial0, partial1]) +
+                            ") AS view_" + partial0.id + partial1.id + "\n";
+                    partialJoin.push({
+                        id: partial0.id + partial1.id,
+                        from: viewFrom,
+                        dimMetrics: dimMetrics,
+                        metrics: mets,
+                        dimensions: dims,
+                        keys: keys,
+                        clauses: partial.clauses,
+                        origin: false
+                    });
+
+                }
+            }
+        }
+
+        /*
+            When only one view remain, the query is made and a ;
+            is added at the end.
+
+            TODO: Probrably this last line adds one more
+            layer to the query, that is in fact unnecessary.
+            Think a way to remove-it.
+        */
+        return this.buildQuery(view, partialJoin) + ";";
     }
 
     private searchMaterializedViews(view: View): View[] {
@@ -90,27 +510,22 @@ export class PostgresAdapter extends Adapter {
         return r;
     }
 
-    private buildQuery(target: View, views: View[]) {
+    private buildQuery(target: View, views: ExpandedView[]) {
         const metrics = target.metrics;
         const dimensions = target.dimensions;
         const clauses = target.clauses;
 
         let dimMap: {[key: string]: DimInfo} = {};
-        let metMap: {[key: string]: View[]} = {};
-        let nameMap: {[key: string]: View} = {};
+        let nameMap: {[key: string]: ExpandedView} = {};
 
         for (let i = 0; i < views.length; ++i) {
             const mets = views[i].metrics;
             const dims = views[i].dimensions;
             for (let j = 0; j < mets.length; ++j) {
-                if (!metMap[mets[j].name])  {
-                    metMap[mets[j].name] = [views[i]];
+                if (!nameMap[mets[j].name])  {
                     nameMap[mets[j].name] = views[i];
                 }
 
-                else {
-                    metMap[mets[j].name].push(views[i]);
-                }
             }
 
             for (let j = 0; j < dims.length; ++j) {
@@ -131,11 +546,12 @@ export class PostgresAdapter extends Adapter {
         // Projection
         const strMetrics = metrics.map((metric) => {
             const view = nameMap[metric.name];
-            let func = this.getAggregateFunction(metric.aggregation, view.origin);
-            let quotedName = "\"" + metric.name + "\"";
-            let extMetric = func + "(" + this.buildColumn(metric, view.id) + ")";
-            return extMetric + " AS " + quotedName;
-        });
+            if (view) {
+                return this.translateMetric(metric, view);
+            }
+
+            return "";
+        }).filter((item) => item !== "");
 
         const parsedDimensions = dimensions.map((dimension) => {
             let dim = dimension;
@@ -143,18 +559,23 @@ export class PostgresAdapter extends Adapter {
                 dim = dim.parent;
             }
             const view = nameMap[dim.name];
-            const quotedName = "\"" + dimension.name + "\"";
-            let extDimension = this.buildColumn(dim, view.id);
-            let aux = dimension;
-            while (aux.name !== dim.name) {
-                extDimension = this.translateRelation(aux.relation, extDimension);
-                aux = aux.parent;
-            }
-            return { aliased: extDimension + " AS " + quotedName, noalias: extDimension };
+            return this.translateDimension(dimension, dim, view);
         });
 
-        const strDimensions = parsedDimensions.map ((item) => item.aliased);
-        const grouped = parsedDimensions.map((item) => item.noalias);
+        let parsedDimMetrics: DimTranslation[] = [];
+
+        for (let i = 0; i < views.length; ++i) {
+            const dimMets = views[i].dimMetrics.map((item) => {
+                return this.translateDimMetric(item, views[i]);
+            });
+
+            parsedDimMetrics = parsedDimMetrics.concat(dimMets);
+        }
+
+        const totalDimensions = parsedDimensions.concat(parsedDimMetrics);
+
+        const strDimensions = totalDimensions.map ((item) => item.aliased);
+        const grouped = totalDimensions.map((item) => item.noalias);
         const elements = strMetrics.concat(strDimensions);
 
         // Joins
@@ -194,14 +615,14 @@ export class PostgresAdapter extends Adapter {
         // Assembly
 
         const projection = "SELECT " + elements.join(",");
-        const source = " FROM " + views.map((view) => "view_" + view.id).join(",");
+        const source = " FROM " + views.map((view) => view.from).join(",");
         const selection = (conds.length > 0) ? " WHERE " + conds.join(" AND ") : "";
         let grouping = "";
         if (grouped.length > 0) {
             grouping = " GROUP BY " + grouped.join(",");
         }
 
-        return projection + source + selection + grouping + ";";
+        return projection + source + selection + grouping;
 
     }
 
@@ -262,7 +683,7 @@ export class PostgresAdapter extends Adapter {
         return "view_" + id + "." + quotedName;
     }
 
-    private translateClause(clause: Clause, map: {[key: string]: View}): string {
+    private translateClause(clause: Clause, map: {[key: string]: ExpandedView}): string {
         const r = clause.filters.map((item) => {
             return this.translateFilter(item, map);
         }).filter((item) => {
@@ -271,7 +692,7 @@ export class PostgresAdapter extends Adapter {
         return r.join(" OR ");
     }
 
-    private translateFilter(filter: Filter, map: {[key: string]: View}): string {
+    private translateFilter(filter: Filter, map: {[key: string]: ExpandedView}): string {
         if (!map[filter.target.name]) {
             return "";
         }
@@ -284,6 +705,32 @@ export class PostgresAdapter extends Adapter {
         return leftSide + op + quotedValue + dataType;
     }
 
+    private translateMetric(metric: Metric, view: ExpandedView): string {
+        const func = this.getAggregateFunction(metric.aggregation, view.origin);
+        const quotedName = "\"" + metric.name + "\"";
+        const extMetric = func + "(" + this.buildColumn(metric, view.id) + ")";
+        return extMetric + " AS " + quotedName;
+    }
+
+    private translateDimMetric(metric: Metric, view: ExpandedView): DimTranslation {
+        const quotedName = "\"" + metric.name + "\"";
+        const extMetric = this.buildColumn(metric, view.id);
+        return { aliased: extMetric + " AS " + quotedName, noalias: extMetric };
+    }
+
+    private translateDimension(dimension: Dimension,
+                               ancestor: Dimension,
+                               view: ExpandedView): DimTranslation {
+        const quotedName = "\"" + dimension.name + "\"";
+        let extDimension = this.buildColumn(ancestor, view.id);
+        let aux = dimension;
+        while (aux.name !== ancestor.name) {
+            extDimension = this.translateRelation(aux.relation, extDimension);
+            aux = aux.parent;
+        }
+        return { aliased: extDimension + " AS " + quotedName, noalias: extDimension };
+    }
+
     private translateOperator(op: FilterOperator): string {
         switch (op) {
             case FilterOperator.EQUAL:
@@ -316,4 +763,49 @@ export class PostgresAdapter extends Adapter {
                 return "";
         }
     }
+
+    private compareKeys(a: Dimension[], b: Dimension[]): number {
+        let length = 0;
+        let res = a.length - b.length;
+        if (a.length < b.length) {
+            length = a.length;
+        }
+        else {
+            length = b.length;
+        }
+
+        for (let i = 0; i < length; ++i) {
+            if (a[i].name < b[i].name) {
+                return -1;
+            }
+
+            else if (a[i].name > b[i].name) {
+                return 1;
+            }
+        }
+
+        return res;
+    }
+
+    private similarDimensions(a: Dimension[], b: Dimension[]): number {
+        let count = 0;
+        for (let i = 0; i < a.length; ++i) {
+            if (b.some((itemB) => a[i].name === itemB.name)) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private removeDuplicatedDimensions(candidateDims: Dimension[]): Dimension[] {
+        let filterDims: { [key: string]: boolean } = {};
+        const dims = [];
+        for (let i = 0;  i < candidateDims.length; ++i) {
+            if (!filterDims[candidateDims[i].name]) {
+                dims.push(candidateDims[i]);
+                filterDims[candidateDims[i].name] = true;
+            }
+        }
+        return dims;
+    }
 }
diff --git a/src/core/engine.spec.ts b/src/core/engine.spec.ts
index 05367a2c90f42ed8b6be77e1aada50f56e1b15fc..62f2f56a9fc3f66fbc2f9f0f523c39ad69a925a5 100644
--- a/src/core/engine.spec.ts
+++ b/src/core/engine.spec.ts
@@ -85,7 +85,7 @@ describe("engine class", () => {
 
     it("should be create a fill that cover the query, that match perfectly with a existent view", () => {
         let query = {
-            metrics : [met[0], met[1], met[2]]
+            metrics : [met[0], met[1], met[2], met[10]]
             , dimensions : [dim[0], dim[7]]
         };
         let optimalView = engine.query(query);
@@ -96,7 +96,7 @@ describe("engine class", () => {
         expect(optimalView.metrics).to.be.an("array");
         expect(optimalView.dimensions).to.be.an("array");
         expect(optimalView.childViews).to.be.an("array");
-        expect(optimalView.metrics).to.have.length(3);
+        expect(optimalView.metrics).to.have.length(4);
         expect(optimalView.dimensions).to.have.length(2);
         expect(optimalView.childViews).to.have.length(0);
 
@@ -149,7 +149,7 @@ describe("engine class", () => {
         expect(optimalView.childViews).to.be.an("array");
         expect(optimalView.metrics).to.have.length(0);
         expect(optimalView.dimensions).to.have.length(2);
-        expect(optimalView.childViews).to.have.length(1);
+        expect(optimalView.childViews).to.have.length(3);
 
         expect(optimalView).satisfy((optView: View) => {
             return optView.dimensions.some((item) => item.name === subdim[0].name);
@@ -175,7 +175,7 @@ describe("engine class", () => {
         expect(optimalView.childViews).to.be.an("array");
         expect(optimalView.metrics).to.have.length(0);
         expect(optimalView.dimensions).to.have.length(2);
-        expect(optimalView.childViews).to.have.length(1);
+        expect(optimalView.childViews).to.have.length(3);
 
         expect(optimalView).satisfy((optView: View) => {
             return optView.dimensions.some((item) => item.name === subdim[2].name);
diff --git a/src/core/engine.ts b/src/core/engine.ts
index 3e39b7bbc37cc72175e7f57567278bc05d2412a5..7305394454be9b384f5ed967ac3c95d1707b05d7 100644
--- a/src/core/engine.ts
+++ b/src/core/engine.ts
@@ -175,7 +175,13 @@ export class Engine {
             };
 
             let view = new View(options);
-            this.addView(view);
+            // this.addView(view);
+            /*
+                This line has been removed for now because not all views can be
+                re-used by other views (unmaterializeble views), and so far this
+                is only detected in the adapter, when this can be detected in
+                engine, than the queries can be added again to the engine
+            */
             return view;
         }
     }
diff --git a/src/core/view.ts b/src/core/view.ts
index ef83f082c68f46bdf3a9f633127163b083416dfa..7634a8fe8e8548c520286a7185b37ead7f7a8942 100644
--- a/src/core/view.ts
+++ b/src/core/view.ts
@@ -31,6 +31,7 @@ export interface LoadView {
 export interface ViewOptions {
     metrics: Metric[];
     dimensions: Dimension[];
+    keys?: Dimension[];
     origin: boolean;
     clauses?: Clause[];
     materialized?: boolean;
@@ -41,6 +42,7 @@ export class View {
     public readonly id: string;
     public readonly metrics: Metric[];
     public readonly dimensions: Dimension[];
+    public readonly keys: Dimension[];
     public readonly clauses: Clause[];
     public readonly materialized: boolean;
     public readonly origin: boolean;
@@ -53,6 +55,12 @@ export class View {
         this.materialized = options.materialized || false;
         this.origin = options.origin || false;
         this.childViews = (options.childViews) ? options.childViews : [];
+        if (options.keys && options.keys.length > 0) {
+            this.keys = options.keys.sort();
+        }
+        else {
+            this.keys = this.dimensions;
+        }
 
         // calculate the id of the view based on it's metrics and dimensions
         const metNames = this.metrics.map((metric) => metric.name);
diff --git a/src/util/configParser.ts b/src/util/configParser.ts
index e2d10ec90abeecbb46d873e9bf3fd5f7553e8901..76bffe2af1c05070292c748fcc138fa96d9acb52 100644
--- a/src/util/configParser.ts
+++ b/src/util/configParser.ts
@@ -36,6 +36,7 @@ export interface ViewParsingOptions {
     dimensions: string[];
     metrics: string[];
     clauses?: string[];
+    keys?: string[];
 }
 
 interface MetricStrOptions {
@@ -156,9 +157,12 @@ export class ConfigParser {
             materialized: true,
             origin: opts.origin,
             childViews: [],
-            clauses: []
+            clauses: [],
+            keys: []
         };
 
+        const keys = (opts.keys) ? opts.keys : [];
+
         for (let i = 0; i < opts.metrics.length; ++i) {
             if (metMap[opts.metrics[i]]) {
                 viewOpt.metrics.push(metMap[opts.metrics[i]]);
@@ -179,6 +183,16 @@ export class ConfigParser {
             }
         }
 
+        for (let i = 0; i < keys.length; ++i) {
+            if (dimMap[keys[i]]) {
+                viewOpt.keys.push(dimMap[opts.dimensions[i]]);
+            }
+
+            else {
+                throw new Error("[Parsing error] Non exist key set to view " + opts.alias);
+            }
+        }
+
         if (opts.clauses) {
             for (let i = 0; i < opts.clauses.length; ++i) {
                 const clause = this.parseClause(opts.clauses[i], metMap, dimMap);
diff --git a/test/postgres/fixtures/view0.json b/test/postgres/fixtures/view0.json
index d22ffb171c6b283b8f75922d450d67843c3879c2..8c421f203045adc50271aa6a6fec72df5c520f41 100644
--- a/test/postgres/fixtures/view0.json
+++ b/test/postgres/fixtures/view0.json
@@ -1,7 +1,7 @@
 [
-{"dim:0":"2017-01-01","dim:7":"1","met:0":"1","met:1":"1","met:2":"1"},
-{"dim:0":"2017-01-02","dim:7":"2","met:0":"2","met:1":"2","met:2":"2"},
-{"dim:0":"2017-01-03","dim:7":"3","met:0":"3","met:1":"3","met:2":"3"},
-{"dim:0":"2017-01-04","dim:7":"4","met:0":"4","met:1":"4","met:2":"4"},
-{"dim:0":"2017-01-05","dim:7":"5","met:0":"5","met:1":"5","met:2":"5"}
+{"dim:0":"2017-01-01","dim:7":"1","met:0":"1","met:1":"1","met:2":"1","met:10":"1"},
+{"dim:0":"2017-01-02","dim:7":"2","met:0":"2","met:1":"2","met:2":"2","met:10":"2"},
+{"dim:0":"2017-01-03","dim:7":"3","met:0":"3","met:1":"3","met:2":"3","met:10":"3"},
+{"dim:0":"2017-01-04","dim:7":"4","met:0":"4","met:1":"4","met:2":"4","met:10":"4"},
+{"dim:0":"2017-01-05","dim:7":"5","met:0":"5","met:1":"5","met:2":"5","met:10":"5"}
 ]
diff --git a/test/postgres/fixtures/view2.json b/test/postgres/fixtures/view2.json
index dbac5978dfeb3465cc863d75d9ff6131b2d5b560..5c9498cee6f08f260c62f2898e8f4769f57ab66f 100644
--- a/test/postgres/fixtures/view2.json
+++ b/test/postgres/fixtures/view2.json
@@ -1,7 +1,7 @@
 [
-{"dim:2":"1","met:5":"1","met:6":"1"},
-{"dim:2":"2","met:5":"2","met:6":"2"},
-{"dim:2":"3","met:5":"3","met:6":"3"},
-{"dim:2":"4","met:5":"4","met:6":"4"},
-{"dim:2":"5","met:5":"5","met:6":"5"}
+{"dim:2":"1","met:5":"1","met:6":"1","met:11":"1"},
+{"dim:2":"2","met:5":"2","met:6":"2","met:11":"2"},
+{"dim:2":"3","met:5":"3","met:6":"3","met:11":"3"},
+{"dim:2":"4","met:5":"4","met:6":"4","met:11":"4"},
+{"dim:2":"5","met:5":"5","met:6":"5","met:11":"5"}
 ]
diff --git a/test/postgres/fixtures/view8.json b/test/postgres/fixtures/view8.json
index 6d4641c9c728fc7a586c8a270ef8f78467c35bb5..40725b32af938b54091b293d42d4396aaa3e06c5 100644
--- a/test/postgres/fixtures/view8.json
+++ b/test/postgres/fixtures/view8.json
@@ -1,7 +1,7 @@
 [
-{"dim:5":"t","dim:6":"1","met:9":"1","met:10":"1","met:11":"1"},
-{"dim:5":"t","dim:6":"2","met:9":"2","met:10":"2","met:11":"2"},
-{"dim:5":"t","dim:6":"3","met:9":"3","met:10":"3","met:11":"3"},
-{"dim:5":"f","dim:6":"4","met:9":"4","met:10":"4","met:11":"4"},
-{"dim:5":"f","dim:6":"5","met:9":"5","met:10":"5","met:11":"5"}
+{"dim:5":"t","dim:6":"1","met:9":"1"},
+{"dim:5":"t","dim:6":"2","met:9":"2"},
+{"dim:5":"t","dim:6":"3","met:9":"3"},
+{"dim:5":"f","dim:6":"4","met:9":"4"},
+{"dim:5":"f","dim:6":"5","met:9":"5"}
 ]
diff --git a/test/scenario.ts b/test/scenario.ts
index af10dd2e26bead3160d9b4cd9a7a64c8194ae64c..856cc9ae37687beec4bb7c3b3a36260a4a0e92dc 100644
--- a/test/scenario.ts
+++ b/test/scenario.ts
@@ -52,6 +52,8 @@ interface AdapterScenario {
     geleView: View;
     notMatchFilterView: View;
     notOriginCount: View;
+    unMaterializebleView: View;
+    partialJoinView: View;
 }
 
 interface DataCtrlScenario {
@@ -224,7 +226,7 @@ const aggrView = new View({
     dimensions: [],
     materialized: false,
     origin: false,
-    childViews: [views[0], views[2], views[3], views[4], views[7], views[8]]
+    childViews: [views[0], views[2], views[3]]
 });
 
 const clauseView = new View({
@@ -330,6 +332,22 @@ const notOriginCount = new View({
     clauses: [clauses.view9dim2]
 });
 
+const unMaterializebleView = new View({
+    metrics: [mets[7], mets[9]],
+    dimensions: [dims[5]],
+    materialized: false,
+    origin: false,
+    childViews: [views[3], views[5], views[7], views[8]]
+});
+
+const partialJoinView = new View({
+    metrics: [mets[7], mets[8]],
+    dimensions: [],
+    materialized: false,
+    origin: false,
+    childViews: [views[3], views[5], views[6]]
+});
+
 export const engineScenario: EngineScenario = {
     metrics: mets,
     dimensions: dims,
@@ -354,7 +372,9 @@ export const adapterScenario: AdapterScenario = {
     gtltView: gtltView,
     geleView: geleView,
     notMatchFilterView: notMatchFilterView,
-    notOriginCount: notOriginCount
+    notOriginCount: notOriginCount,
+    unMaterializebleView: unMaterializebleView,
+    partialJoinView: partialJoinView
 };
 
 export const dataCtrlScenario: DataCtrlScenario = {