diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 5fc8e5b..709d1ad 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -126,8 +126,9 @@ static RelOptInfo *create_ordered_paths(PlannerInfo *root,
 					 RelOptInfo *input_rel,
 					 double limit_tuples);
 static PathTarget *make_scanjoin_target(PlannerInfo *root, List *tlist,
-					 AttrNumber **groupColIdx);
+										AttrNumber **groupColIdx, bool* splitted_projection);
 static int	get_grouping_column_index(Query *parse, TargetEntry *tle);
+static int	get_sort_column_index(Query *parse, TargetEntry *tle);
 static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
 static List *select_active_windows(PlannerInfo *root, WindowFuncLists *wflists);
 static List *make_windowInputTargetList(PlannerInfo *root,
@@ -1381,6 +1382,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
 	RelOptInfo *current_rel;
 	RelOptInfo *final_rel;
 	ListCell   *lc;
+	bool splitted_projection = false;
 
 	/* Tweak caller-supplied tuple_fraction if have LIMIT/OFFSET */
 	if (parse->limitCount || parse->limitOffset)
@@ -1657,7 +1659,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
 		 * that were obtained within query_planner().
 		 */
 		sub_target = make_scanjoin_target(root, tlist,
-										  &groupColIdx);
+										  &groupColIdx, &splitted_projection);
 
 		/*
 		 * Forcibly apply that tlist to all the Paths for the scan/join rel.
@@ -1801,6 +1803,13 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
 	{
 		Path	   *path = (Path *) lfirst(lc);
 
+		if (splitted_projection)
+		{			
+			path = apply_projection_to_path(root, current_rel,
+											path, create_pathtarget(root, tlist));
+		}
+
+
 		/*
 		 * If there is a FOR [KEY] UPDATE/SHARE clause, add the LockRows node.
 		 * (Note: we intentionally test parse->rowMarks not root->rowMarks
@@ -3775,15 +3784,17 @@ create_ordered_paths(PlannerInfo *root,
 static PathTarget *
 make_scanjoin_target(PlannerInfo *root,
 					 List *tlist,
-					 AttrNumber **groupColIdx)
+					 AttrNumber **groupColIdx,
+	                 bool* splitted_projection)
 {
 	Query	   *parse = root->parse;
-	List	   *sub_tlist;
-	List	   *non_group_cols;
+	List	   *sub_tlist = NIL;
+	List	   *non_group_cols = NIL;
 	List	   *non_group_vars;
 	int			numCols;
 
 	*groupColIdx = NULL;
+	*splitted_projection = false;
 
 	/*
 	 * If we're not grouping or aggregating or windowing, there's nothing to
@@ -3791,14 +3802,66 @@ make_scanjoin_target(PlannerInfo *root,
 	 */
 	if (!parse->hasAggs && !parse->groupClause && !parse->groupingSets &&
 		!root->hasHavingQual && !parse->hasWindowFuncs)
+	{
+		if (parse->sortClause && limit_needed(parse)) {
+			ListCell   *tl;
+			bool contains_non_vars = false;
+			foreach(tl, tlist)
+			{
+				TargetEntry *tle = (TargetEntry *) lfirst(tl);
+				int			colno;
+				
+				colno = get_sort_column_index(parse, tle);
+				if (colno >= 0)
+				{
+					TargetEntry *newtle;
+					
+					newtle = makeTargetEntry(tle->expr,
+											 list_length(sub_tlist) + 1,
+											 NULL,
+											 false);
+					sub_tlist = lappend(sub_tlist, newtle);
+				}
+				else
+				{
+					/*
+					 * Non-sorting column, so just remember the expression for
+					 * later call to pull_var_clause.  There's no need for
+					 * pull_var_clause to examine the TargetEntry node itself.
+					 */
+					non_group_cols = lappend(non_group_cols, tle->expr);
+					contains_non_vars |= !(tle->expr && IsA(tle->expr, Var));
+				}
+			}
+						
+			if (non_group_cols) /* there are some columns not used in order by */
+			{ 
+				non_group_vars = pull_var_clause((Node *) non_group_cols,
+												 PVC_RECURSE_AGGREGATES,
+												 PVC_INCLUDE_PLACEHOLDERS);
+				sub_tlist = add_to_flat_tlist(sub_tlist, non_group_vars);
+				/* clean up cruft */
+				list_free(non_group_vars);
+				list_free(non_group_cols);
+
+				if (contains_non_vars) 
+				{ 
+					/*
+					 * This optimization makes sense only if target list contains some complex expressions, 
+					 * for example functions calls. May be it is better to check cost of this expressions,
+					 * but right now just apply this optimization if there are non-vars columns 
+					 */
+					tlist = sub_tlist;
+					*splitted_projection = true;
+				}
+			}
+		} 
 		return create_pathtarget(root, tlist);
-
+	}
 	/*
 	 * Otherwise, we must build a tlist containing all grouping columns, plus
 	 * any other Vars mentioned in the targetlist and HAVING qual.
 	 */
-	sub_tlist = NIL;
-	non_group_cols = NIL;
 
 	numCols = list_length(parse->groupClause);
 	if (numCols > 0)
@@ -3918,6 +3981,38 @@ get_grouping_column_index(Query *parse, TargetEntry *tle)
 }
 
 /*
+ * get_sort_column_index
+ *		Get the ORDER BY column position, if any, of a targetlist entry.
+ *
+ * Returns the index (counting from 0) of the TLE in the ORDER BY list, or -1
+ * if it's not a sorting column.  Note: the result is unique because the
+ * parser won't make multiple sortClause entries for the same TLE.
+ */
+static int
+get_sort_column_index(Query *parse, TargetEntry *tle)
+{
+	int			colno = 0;
+	Index		ressortgroupref = tle->ressortgroupref;
+	ListCell   *gl;
+
+	/* No need to search groupClause if TLE hasn't got a sortgroupref */
+	if (ressortgroupref == 0)
+		return -1;
+
+	foreach(gl, parse->sortClause)
+	{
+		SortGroupClause *sortcl = (SortGroupClause *) lfirst(gl);
+
+		if (sortcl->tleSortGroupRef == ressortgroupref)
+			return colno;
+		colno++;
+	}
+
+	return -1;
+}
+
+
+/*
  * postprocess_setop_tlist
  *	  Fix up targetlist returned by plan_set_operations().
  *
