/// <summary>
        /// Attempts to merge group columns with select/order columns, returns group columns which were not used in select.
        /// </summary>
        private IEnumerable <QueryGroupColumnData> MergeAndGetOrphanGroupColumns()
        {
            if (_queryParts.Groups.Count == 1)
            {
                foreach (var selectColumn in _queryParts.Select)
                {
                    var shouldReplaceColumnPath =
                        (selectColumn.AggregationType.HasValue && string.IsNullOrEmpty(selectColumn.ColumnPath)) ||
                        (!selectColumn.AggregationType.HasValue && selectColumn.ColumnPath == "Key");

                    if (shouldReplaceColumnPath)
                    {
                        selectColumn.ColumnPath = _queryParts.Groups.First().ColumnPath;
                    }
                }
            }

            foreach (var groupColumn in _queryParts.Groups)
            {
                // in some cases ColumnPath contains wrong ESQ column path
                // because of re-linq tree visit rules. All cases are described:
                Func <QuerySelectColumnData, bool> selector = (column) =>
                                                              // case:
                                                              // .GroupBy(item => new object[] { item.Column<int>("Column1"), item.Column<string>("Column2") })
                                                              // .Select(group => new { Column1 = group.Key[0], Column2 = group.Key[1] })
                                                              column.ColumnPath == QueryUtils.GetIndexMemberName(groupColumn.Position)
                                                              // case:
                                                              // .GroupBy(item => new { Column1 = item.Column<int>("Column1"), Column2 = item.Column<string>("Column2") })
                                                              // .Select(group => new { Alias1 = group.Key.Column1, Alias2 = group.Key.Column2 })
                                                              || column.ColumnPath == QueryUtils.GetAliasMemberName(groupColumn.Alias)
                                                              // case:
                                                              // .GroupBy(item => item.Column<int>("Column1"))
                                                              // .Select(group => new { Alias1 = group.Key })
                                                              || !column.AggregationType.HasValue && column.ColumnPath == QueryUtils.SingleGroupColumnAlias
                                                              // case (aggregate columns have no column path):
                                                              // .GroupBy(item => item.Column<int>("Column1"))
                                                              // .Select(group => new { Alias1 = group.Key, Count = group.Count() })
                                                              || column.AggregationType.HasValue && string.IsNullOrEmpty(column.ColumnPath);

                // get select columns with incorrect column path
                var selectKeyColumns = _queryParts.Select
                                       .Where(selector)
                                       .ToArray();

                // same for order columns
                var orderKeyColumns = _queryParts.Orders
                                      .Where(selector)
                                      .ToArray();

                // 1. if column is contained in both Select/OrderBy AND GroupBy clause, then it will be added to ESQ
                //    in Select/OrderBy block and should not be added again in GroupBy block.
                // 2. if column is only contained in GroupBy clause, it will not be added in Select/OrderBy block
                //    and query will be broken - so we need to add it in GroupBy block, hence yield return.
                if (selectKeyColumns.Any() || orderKeyColumns.Any())
                {
                    selectKeyColumns.ForEach(column => column.ColumnPath = groupColumn.ColumnPath);
                    orderKeyColumns.ForEach(column => column.ColumnPath  = groupColumn.ColumnPath);
                }
                else
                {
                    yield return(groupColumn);
                }
            }
        }