diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts
index 685963c48d1c85d59647f35c9289ea065584446a..fc5af7bbd14e467357ac171fcb0147c73dc3ff36 100644
--- a/src/adapter/postgres.ts
+++ b/src/adapter/postgres.ts
@@ -22,16 +22,13 @@ import { Adapter } from "../core/adapter";
 import { Metric } from "../core/metric";
 import { Dimension } from "../core/dimension";
 import { AggregationType, RelationType } from "../common/types";
-import { View, ChildView } from "../core/view";
+import { View } from "../core/view";
 import { Pool, PoolConfig } from "pg";
 
-interface ParsedChild {
-    query: string;
-    view: View;
-    dimensions: Dimension[];
-    metrics: Metric[];
-    alias: string;
-};
+interface DimInfo {
+    dim: Dimension;
+    views: View[];
+}
 
 export class PostgresAdapter extends Adapter {
     private pool: Pool;
@@ -42,7 +39,20 @@ export class PostgresAdapter extends Adapter {
     }
     public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void {
         // buildQueryFromView does not put the final ;, it need to be put apart
-        let query =  this.buildQueryFromView(view, view.metrics, view.dimensions) + ";\n";
+        // let query =  this.buildQueryFromView(view, view.metrics, view.dimensions) + ";\n";
+
+        const materialized = this.searchMaterializedViews(view).sort((a, b) => {
+            return (a.id < b.id) ? -1 : 1;
+        });
+
+        const unique = [materialized[0]];
+        for (let i = 1; i < materialized.length; ++i) {
+            if (materialized[i - 1].id !== materialized[i].id) {
+                unique.push(materialized[i]);
+            }
+        }
+
+        const query = this.buildQuery(view, unique);
         this.pool.connect((err, client, done) => {
             if (err) {
                 cb (err);
@@ -60,136 +70,6 @@ export class PostgresAdapter extends Adapter {
         return false;
     }
 
-    private buildQueryFromView (view: View, metrics: Metric[], dimensions: Dimension[]): string {
-        /*
-            Reduce metrics and dimensions array to the intersection with the
-             view. So is possible only get useful data in the sub-querys.
-        */
-        let strMetrics = metrics.map((metric) => {
-            let func = this.getAggregateFunction(metric.aggregation, view.origin);
-            let quotedName = "\"" + metric.name + "\"";
-            let extMetric = func + "(" + quotedName + ") AS " + quotedName;
-            return extMetric;
-        });
-
-        if (view.materialized) {
-            let strDimensions = dimensions.map((dimension) => "\"" + dimension.name + "\"");
-            let sql = "(SELECT " + strMetrics.concat(strDimensions).join(", ");
-            sql += " FROM " + "view_" + view.id;
-            if (strDimensions.length > 0 && strMetrics.length > 0) {
-                sql += " GROUP BY " + strDimensions.join(", ");
-            }
-            sql += ")";
-            return sql;
-        }
-
-        else {
-
-            let covered = new Map();
-            let matchable: any[] = [] ;
-            dimensions.forEach((item) => {
-                covered.set(item.name, "");
-                /*
-                    For each dimension that must be covered
-                    create a match in the array.
-                    If a more than onde view match to the same
-                    dimension, cretes a WHERE clause
-                */
-                matchable.push({match: item.name, sub: item});
-                let dim = item;
-                /*
-                    Sub dimensions also have parents that can match
-                    with then too.
-                */
-                while (dim.relation !== RelationType.NONE) {
-                    dim = dim.parent;
-                    matchable.push({
-                        match: dim.name,
-                        sub: item,
-                    });
-                }
-            });
-            metrics.forEach((item) => covered.set(item.name, ""));
-
-            let elements: string[] = [];
-            let group: string[] = [];
-            let viewsQuery: string[] = [];
-            let selected: string[] = [];
-
-            let children: ParsedChild[] = view.childViews.map((item: ChildView) => {
-                let dims = item.view.dimensions.filter((dim) => {
-                    return matchable.some((match) => match.match === dim.name);
-                });
-
-                let mets = item.metrics.filter((met) => {
-                    return metrics.some((elem) => elem.name === met.name);
-                });
-                let query = "";
-                if (dims.length !== 0 || mets.length !== 0) {
-                    query = this.buildQueryFromView(item.view, mets, dims);
-                }
-                return {
-                    query: query,
-                    view: item.view,
-                    dimensions : dims,
-                    metrics: mets,
-                    alias: "alias_" + item.view.id
-                };
-            }).filter ((item) => item.query !== "");
-
-            children.forEach((child: ParsedChild) => {
-                child.view.dimensions.forEach((dimension: Dimension) => {
-                    /*
-                        Make selection. Search for dimensions, that are in
-                        matchable array.
-                    */
-                    matchable.filter((item) => {
-                        return item.match === dimension.name;
-                    })
-                    .forEach((item) => {
-                        // Expand the sub-dimension until match with a parent
-                        let dim = item.sub;
-                        let extDimension = child.alias + ".\"" + dimension.name + "\"";
-                        while (dim.name !== item.match) {
-                            extDimension = this.translateRelation(dim.relation, extDimension);
-                            dim = dim.parent;
-                        }
-
-                        if (covered.get(item.sub.name) === "") {
-                            elements.push(extDimension + " AS \"" + item.sub.name + "\"");
-                            covered.set(item.sub.name, extDimension);
-                            group.push(extDimension);
-                        }
-                        else {
-                            selected.push(extDimension + " = " + covered.get(item.sub.name));
-                        }
-                    });
-                });
-
-                child.metrics.forEach((metric: Metric) => {
-                    // Only materialized views can have origin as true
-                    let func = this.getAggregateFunction(metric.aggregation, false);
-                    let quotedName = "\"" + metric.name + "\"";
-                    let extMetric = func + "(" + child.alias + "." + quotedName + ") AS " + quotedName;
-                    elements.push(extMetric);
-                });
-
-                viewsQuery.push(child.query + " AS " + child.alias);
-
-            });
-
-            let projection = "SELECT " + elements.join(", ") + "\n";
-            let viewsFrom = "FROM " + viewsQuery.join(", ") + "\n";
-            let selection = (selected.length > 0) ? "WHERE " + selected.join(" AND ") + "\n" : "";
-            let grouping =  "";
-            if (group.length > 0 && metrics.length > 0) {
-                grouping = "GROUP BY " + group.join(", ") + "\n";
-            }
-
-            return "(" +  projection + viewsFrom + selection + grouping + ")";
-        }
-    }
-
     private getAggregateFunction(aggrType: AggregationType, origin: boolean): string {
         switch (aggrType) {
             case AggregationType.SUM:
@@ -237,4 +117,116 @@ export class PostgresAdapter extends Adapter {
         */
         return name + "(" + args.map((item, idx) => item + values[idx]).join(",") + ")";
     }
+
+    private searchMaterializedViews(view: View): View[] {
+        let r: View[] = [];
+        if (view.materialized) {
+            return [view];
+        }
+
+        else {
+            let children = view.childViews.map((item) => item.view);
+            for (let i = 0; i < children.length; ++i) {
+                r = r.concat(this.searchMaterializedViews(children[i]));
+            }
+        }
+
+        return r;
+    }
+
+    private buildQuery(target: View, views: View[]) {
+        const metrics = target.metrics;
+        const dimensions = target.dimensions;
+
+        let dimMap: {[key: string]: DimInfo} = {};
+        let metMap: {[key: string]: View[]} = {};
+
+        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]];
+                }
+
+                else {
+                    metMap[mets[j].name].push(views[i]);
+                }
+            }
+
+            for (let j = 0; j < dims.length; ++j) {
+                if (!dimMap[dims[j].name])  {
+                    dimMap[dims[j].name] = {
+                        dim: dims[j],
+                        views: [views[i]]
+                    };
+                }
+
+                else {
+                    dimMap[dims[j].name].views.push(views[i]);
+                }
+            }
+        }
+
+        const strMetrics = metrics.map((metric) => {
+            const view = metMap[metric.name][0];
+            let func = this.getAggregateFunction(metric.aggregation, view.origin);
+            let quotedName = "\"" + metric.name + "\"";
+            let extMetric = func + "(view_" + view.id + "." + quotedName + ")";
+            return extMetric + " AS " + quotedName;
+        });
+
+        const parsedDimensions = dimensions.map((dimension) => {
+            let dim = dimension;
+            while (!dimMap[dim.name]) {
+                // Checar exeção
+                dim = dim.parent;
+            }
+            const view = dimMap[dim.name].views[0];
+            const quotedDim = "\"" + dim.name + "\"";
+            const quotedName = "\"" + dimension.name + "\"";
+            let extDimension = "view_" + view.id + "." + quotedDim;
+            let aux = dimension;
+            while (aux.name !== dim.name) {
+                extDimension = this.translateRelation(aux.relation, extDimension);
+                aux = aux.parent;
+            }
+            return { aliased: extDimension + " AS " + quotedName, noalias: extDimension };
+        });
+
+        const strDimensions = parsedDimensions.map ((item) => item.aliased);
+        const grouped = parsedDimensions.map((item) => item.noalias);
+        const elements = strMetrics.concat(strDimensions);
+
+        let joins = [];
+        for (let i in dimMap) {
+            let remainViews = dimMap[i].views.slice();
+            let dim = dimMap[i].dim;
+            let leftSide = this.buildColumn(dim, remainViews.shift().id);
+            if (remainViews.length > 0) {
+                while (remainViews.length > 0) {
+                    const id = remainViews.shift().id;
+                    const rightSide = this.buildColumn(dim, id);
+                    joins.push(leftSide + " = " + rightSide);
+                }
+            }
+
+        }
+
+        const projection = "SELECT " + elements.join(",");
+        const source = " FROM " + views.map((view) => "view_" + view.id).join(",");
+        const selection = (joins.length > 0) ? " WHERE " + joins.join(" AND ") : "";
+        let grouping = "";
+        if (grouped.length > 0) {
+            grouping = " GROUP BY " + grouped.join(",");
+        }
+
+        return projection + source + selection + grouping + ";";
+
+    }
+
+    private buildColumn (item: Metric|Dimension, id: string): string {
+        const quotedName = "\"" + item.name + "\"";
+        return "view_" + id + "." + quotedName;
+    }
 }
diff --git a/test/scenario.ts b/test/scenario.ts
index 45a428c19f13a2e1a8bccf195897380281f846d6..1e5e33e0ab67d96384ab6b2469f7e4bc9cd8f703 100644
--- a/test/scenario.ts
+++ b/test/scenario.ts
@@ -152,6 +152,11 @@ const aggrView = new View({
             view: views[2],
             metrics: [mets[6]],
             dimensions: []
+        },
+        {
+            view: views[4],
+            metrics: [],
+            dimensions: []
         }
     ]
 });