package ru.yandex.webmaster3.storage.searchquery.dao;

import lombok.Setter;
import org.joda.time.LocalDate;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.searchquery.QueryId;
import ru.yandex.webmaster3.core.searchquery.QueryIndicator;
import ru.yandex.webmaster3.storage.searchquery.DeviceType;
import ru.yandex.webmaster3.storage.searchquery.QueryStat;
import ru.yandex.webmaster3.storage.searchquery.RegionInclusion;
import ru.yandex.webmaster3.storage.util.clickhouse2.AbstractClickhouseDao;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseException;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseQueryContext;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author avhaliullin
 */
public class AbstractQueriesStatsCHDao extends AbstractClickhouseDao {

    @Setter
    protected QueryStatisticsFiltersService queryStatisticsFiltersService;

    protected String getQueryIdsString(List<QueryId> queryIds) {
        return queryIds.stream().map(l -> Long.toString(l.getQueryId())).collect(Collectors.joining(","));
    }

    protected boolean isPosition(QueryIndicator orderBy) {
        switch (orderBy) {
            case AVERAGE_CLICK_POSITION:
            case AVERAGE_CLICK_POSITION_2_3:
            case AVERAGE_CLICK_POSITION_4_10:
            case AVERAGE_CLICK_POSITION_11_50:
            case AVERAGE_SHOW_POSITION:
            case AVERAGE_SHOW_POSITION_2_3:
            case AVERAGE_SHOW_POSITION_4_10:
            case AVERAGE_SHOW_POSITION_11_50:
                return true;
        }
        return false;
    }

    @SuppressWarnings("Duplicates")
    protected List<QueryStat> getQueryStat(String tableName, Integer shard, WebmasterHostId hostId,
            LocalDate dateFrom, LocalDate dateTo,
            RegionInclusion regionInclusion, Set<Integer> regionIds,
            List<QueryId> queryIds, List<QueryIndicator> indicators, DeviceType deviceType)
            throws ClickhouseException
    {
        if (queryIds.isEmpty()) {
            return Collections.emptyList();
        }
        String regionFilter = queryStatisticsFiltersService.getRegionFilter(regionInclusion, regionIds);
        if (!regionFilter.isEmpty()) {
            regionFilter = "AND " + regionFilter;
        }
        StringBuilder qBuilder = new StringBuilder();
        Set<String> columnSet = new HashSet<>();

        qBuilder.append("SELECT "
                + "date"
                + ", query_id");

        addQueryColumns(columnSet, indicators);
        appendAggregationColumns(qBuilder, columnSet);

        qBuilder.append(
                " FROM " + tableName
                + " WHERE host_id = '" + hostId.toStringId() + "'"
                + " AND date >= '" + dateFrom.toString() + "'"
                + " AND date <= '" + dateTo.toString() + "'"
                + " AND query_id IN (" + getQueryIdsString(queryIds) + ")"
                + " " + regionFilter
                + " AND " + deviceType.getQueryFilter()
                + " GROUP BY date, query_id"
        );

//        String q = "SELECT date"
//                + ", query_id"
//                + ", sum(shows_1) as " + F.S1
//                + ", sum(clicks_1) as " + F.C1
//                + ", sum(shows_2_3) as " + F.S2_3
//                + ", sum(clicks_2_3) as " + F.C2_3
//                + ", sum(shows_4_10) as " + F.S4_10
//                + ", sum(clicks_4_10) as " + F.C4_10
//                + ", sum(shows_11_50) as " + F.S11_50
//                + ", sum(clicks_11_50) as " + F.C11_50
//                + ", (S1+S2_3+S4_10+S11_50) as " + F.ST
//                + ", (C1+C2_3+C4_10+C11_50) as " + F.CT
//                + ", sum(agr_pos_shows_2_3) as " + F.APS2_3
//                + ", sum(agr_pos_clicks_2_3) as " + F.APC2_3
//                + ", sum(agr_pos_shows_4_10) as " + F.APS4_10
//                + ", sum(agr_pos_clicks_4_10) as " + F.APC4_10
//                + ", sum(agr_pos_shows_11_50) as " + F.APS11_50
//                + ", sum(agr_pos_clicks_11_50) as " + F.APC11_50
//                + ", sum(serps_total) as " + F.SRP
//                + " FROM " + tableName
//                + " WHERE host_id = '" + hostId.toStringId() + "'"
//                + " AND date >= '" + dateFrom.toString() + "'"
//                + " AND date <= '" + dateTo.toString() + "'"
//                + " AND query_id IN (" + idsStr + ")"
//                + " " + regionFilter
//                + " GROUP BY date, query_id";

        ClickhouseQueryContext.Builder ctx = ClickhouseQueryContext.useDefaults();
        if (shard != null){
            ctx = ctx.setHost(getClickhouseServer().pickAliveHostOrFail(shard));
        }
        List<QueryStat> result = getClickhouseServer().queryAll(ctx, qBuilder.toString(), row -> {
            LocalDate date = row.getLocalDate("date");
            long queryId = row.getLongUnsafe("query_id");
            long totalShows = 0;
            long totalClicks = 0;
            long shows_1 = 0;
            long clicks_1 = 0;
            long shows_2_3 = 0;
            long clicks_2_3 = 0;
            long shows_4_10 = 0;
            long clicks_4_10 = 0;
            long shows_11_50 = 0;
            long clicks_11_50 = 0;
            long agr_shows_2_3 = 0;
            long agr_clicks_2_3 = 0;
            long agr_shows_4_10 = 0;
            long agr_clicks_4_10 = 0;
            long agr_shows_11_50 = 0;
            long agr_clicks_11_50 = 0;
            long totalSerps = 0;

            for (String column : columnSet) {
                switch (column) {
                    case F.ST:      totalShows = row.getLongUnsafe(F.ST); break;
                    case F.CT:      totalClicks = row.getLongUnsafe(F.CT); break;
                    case F.S1:      shows_1 = row.getLongUnsafe(F.S1); break;
                    case F.C1:      clicks_1 = row.getLongUnsafe(F.C1); break;
                    case F.S2_3:    shows_2_3 = row.getLongUnsafe(F.S2_3); break;
                    case F.C2_3:    clicks_2_3 = row.getLongUnsafe(F.C2_3); break;
                    case F.S4_10:   shows_4_10 = row.getLongUnsafe(F.S4_10); break;
                    case F.C4_10:   clicks_4_10 = row.getLongUnsafe(F.C4_10); break;
                    case F.S11_50:  shows_11_50 = row.getLongUnsafe(F.S11_50); break;
                    case F.C11_50:  clicks_11_50 = row.getLongUnsafe(F.C11_50); break;

                    case F.APS2_3:  agr_shows_2_3 = row.getLongUnsafe(F.APS2_3); break;
                    case F.APC2_3:  agr_clicks_2_3 = row.getLongUnsafe(F.APC2_3); break;
                    case F.APS4_10: agr_shows_4_10 = row.getLongUnsafe(F.APS4_10); break;
                    case F.APC4_10: agr_clicks_4_10 = row.getLongUnsafe(F.APC4_10); break;
                    case F.APS11_50: agr_shows_11_50 = row.getLongUnsafe(F.APS11_50); break;
                    case F.APC11_50: agr_clicks_11_50 = row.getLongUnsafe(F.APC11_50); break;

                    case F.SRP: totalSerps = row.getLongUnsafe(F.SRP); break;
                }
            }

            return new QueryStat(date, new QueryId(queryId),
                    totalShows, totalClicks,
                    shows_1, clicks_1,
                    shows_2_3, clicks_2_3,
                    shows_4_10, clicks_4_10,
                    shows_11_50, clicks_11_50,
                    agr_shows_2_3, agr_clicks_2_3,
                    agr_shows_4_10, agr_clicks_4_10,
                    agr_shows_11_50, agr_clicks_11_50,
                    totalSerps
            );
        });
        result.sort((s1, s2) -> s1.getDate().compareTo(s2.getDate()));
        return result;
    }

    protected void appendAggregationColumns(StringBuilder qBuilder, Set<String> columnSet) {
        for (String column : columnSet) {
            switch (column) {
                case F.ST:      qBuilder.append(", sum(shows_1 + shows_2_3 + shows_4_10 + shows_11_50) as " + F.ST); break;
                case F.CT:      qBuilder.append(", sum(clicks_1 + clicks_2_3 + clicks_4_10 + clicks_11_50) as " + F.CT); break;
                case F.S1:      qBuilder.append(", sum(shows_1) as " + F.S1); break;
                case F.C1:      qBuilder.append(", sum(clicks_1) as " + F.C1); break;
                case F.S2_3:    qBuilder.append(", sum(shows_2_3) as " + F.S2_3); break;
                case F.C2_3:    qBuilder.append(", sum(clicks_2_3) as " + F.C2_3); break;
                case F.S4_10:   qBuilder.append(", sum(shows_4_10) as " + F.S4_10); break;
                case F.C4_10:   qBuilder.append(", sum(clicks_4_10) as " + F.C4_10); break;
                case F.S11_50:  qBuilder.append(", sum(shows_11_50) as " + F.S11_50); break;
                case F.C11_50:  qBuilder.append(", sum(clicks_11_50) as " + F.C11_50); break;
                case F.APS2_3:  qBuilder.append(", sum(agr_pos_shows_2_3) as " + F.APS2_3); break;
                case F.APC2_3:  qBuilder.append(", sum(agr_pos_clicks_2_3) as " + F.APC2_3); break;
                case F.APS4_10: qBuilder.append(", sum(agr_pos_shows_4_10) as " + F.APS4_10); break;
                case F.APC4_10: qBuilder.append(", sum(agr_pos_clicks_4_10) as " + F.APC4_10); break;
                case F.APS11_50: qBuilder.append(", sum(agr_pos_shows_11_50) as " + F.APS11_50); break;
                case F.APC11_50: qBuilder.append(", sum(agr_pos_clicks_11_50) as " + F.APC11_50); break;
                case F.SRP:     qBuilder.append(", sum(serps_total) as " + F.SRP); break;
            }
        }
    }

    @SuppressWarnings("Duplicates")
    protected void addQueryColumns(Set<String> columnSet, List<QueryIndicator> indicators) {
        for (QueryIndicator indicator : indicators) {
            switch (indicator) {
                case SHOWS_1_50:
                case TOTAL_SHOWS_COUNT:
                    columnSet.add(F.ST);
                    break;

                case CLICKS_1_50:
                case TOTAL_CLICKS_COUNT:
                    columnSet.add(F.CT);
                    break;

                case TOTAL_CTR:
                    columnSet.add(F.ST);
                    columnSet.add(F.CT);
                    break;

                case TOTAL_SERPS_COUNT:
                    columnSet.add(F.SRP);
                    break;

                case SHOWS_COUNT_1:
                    columnSet.add(F.S1);
                    break;

                case CLICKS_COUNT_1:
                    columnSet.add(F.C1);
                    break;

                case SHOWS_COUNT_2_3:
                    columnSet.add(F.S2_3);
                    break;

                case CLICKS_COUNT_2_3:
                    columnSet.add(F.C2_3);
                    break;

                case SHOWS_COUNT_4_10:
                    columnSet.add(F.S4_10);
                    break;

                case CLICKS_COUNT_4_10:
                    columnSet.add(F.C4_10);
                    break;

                case SHOWS_COUNT_11_50:
                    columnSet.add(F.S11_50);
                    break;

                case CLICKS_COUNT_11_50:
                    columnSet.add(F.C11_50);
                    break;

                case CTR_1:
                    columnSet.add(F.S1);
                    columnSet.add(F.C1);
                    break;

                case CTR_2_3:
                    columnSet.add(F.S2_3);
                    columnSet.add(F.C2_3);
                    break;

                case CTR_4_10:
                    columnSet.add(F.S4_10);
                    columnSet.add(F.C4_10);
                    break;

                case CTR_11_50:
                    columnSet.add(F.S11_50);
                    columnSet.add(F.C11_50);
                    break;

                case AVERAGE_SHOW_POSITION:
                    columnSet.add(F.ST);
                    columnSet.add(F.S1);
                    columnSet.add(F.APS2_3);
                    columnSet.add(F.APS4_10);
                    columnSet.add(F.APS11_50);
                    break;

                case AVERAGE_CLICK_POSITION:
                    columnSet.add(F.CT);
                    columnSet.add(F.C1);
                    columnSet.add(F.APC2_3);
                    columnSet.add(F.APC4_10);
                    columnSet.add(F.APC11_50);
                    break;

                case AVERAGE_SHOW_POSITION_2_3:
                    columnSet.add(F.S2_3);
                    columnSet.add(F.APS2_3);
                    break;

                case AVERAGE_CLICK_POSITION_2_3:
                    columnSet.add(F.C2_3);
                    columnSet.add(F.APC2_3);
                    break;

                case AVERAGE_SHOW_POSITION_4_10:
                    columnSet.add(F.S4_10);
                    columnSet.add(F.APS4_10);
                    break;

                case AVERAGE_CLICK_POSITION_4_10:
                    columnSet.add(F.C4_10);
                    columnSet.add(F.APC4_10);
                    break;

                case AVERAGE_SHOW_POSITION_11_50:
                    columnSet.add(F.S11_50);
                    columnSet.add(F.APS11_50);
                    break;

                case AVERAGE_CLICK_POSITION_11_50:
                    columnSet.add(F.C11_50);
                    columnSet.add(F.APC11_50);
                    break;
            }
        }
    }

    protected String getOrderColumns(QueryIndicator indicator, String currentRangeCondition) {
        Set<String> columns = new HashSet<>();

        switch (indicator) {
            case TOTAL_SHOWS_COUNT:
                columns.add(Q.ST_q);
                break;
            case TOTAL_CLICKS_COUNT:
                columns.add(Q.CT_q);
                break;
            case TOTAL_SERPS_COUNT:
                columns.add(Q.SRP_q);
                break;
            case SHOWS_COUNT_1:
                columns.add(Q.S1_q);
                break;
            case CLICKS_COUNT_1:
                columns.add(Q.C1_q);
                break;
            case SHOWS_COUNT_2_3:
                columns.add(Q.S2_3_q);
                break;
            case CLICKS_COUNT_2_3:
                columns.add(Q.C2_3_q);
                break;
            case SHOWS_COUNT_4_10:
                columns.add(Q.S4_10_q);
                break;
            case CLICKS_COUNT_4_10:
                columns.add(Q.C4_10_q);
                break;
            case SHOWS_COUNT_11_50:
                columns.add(Q.S11_50_q);
                break;
            case CLICKS_COUNT_11_50:
                columns.add(Q.C11_50_q);
                break;

            case CLICKS_DYNAMICS:
                columns.add(String.format(Q.CD_PATTERN, currentRangeCondition));

            case TOTAL_CTR:
                columns.add(Q.ST_q);
                columns.add(Q.CT_q);
                columns.add(Q.STnz_q);
                columns.add(Q.CTR_q);
                break;
            case CTR_1:
                columns.add(Q.S1_q);
                columns.add(Q.C1_q);
                columns.add(Q.S1nz_q);
                columns.add(Q.CTR1_q);
                break;
            case CTR_2_3:
                columns.add(Q.S2_3_q);
                columns.add(Q.C2_3_q);
                columns.add(Q.S2_3nz_q);
                columns.add(Q.CTR2_3_q);
                break;
            case CTR_4_10:
                columns.add(Q.S4_10_q);
                columns.add(Q.C4_10_q);
                columns.add(Q.S4_10nz_q);
                columns.add(Q.CTR4_10_q);
                break;
            case CTR_11_50:
                columns.add(Q.S11_50_q);
                columns.add(Q.C11_50_q);
                columns.add(Q.S11_50nz_q);
                columns.add(Q.CTR11_50_q);
                break;

            case AVERAGE_SHOW_POSITION:
                columns.add(Q.S1_q);
                columns.add(Q.S2_3_q);
                columns.add(Q.S4_10_q);
                columns.add(Q.S11_50_q);
                columns.add(Q.APS2_3_q);
                columns.add(Q.APS4_10_q);
                columns.add(Q.APS11_50_q);
                columns.add(Q.APS1_50_q);
                columns.add(Q.S1_50_q);
                columns.add(Q.S1_50nz_q);
                columns.add(Q.POS_0_q);
                columns.add(Q.POS_q);
                break;

            case AVERAGE_CLICK_POSITION:
                columns.add(Q.C1_q);
                columns.add(Q.C2_3_q);
                columns.add(Q.C4_10_q);
                columns.add(Q.C11_50_q);
                columns.add(Q.APC2_3_q);
                columns.add(Q.APC4_10_q);
                columns.add(Q.APC11_50_q);
                columns.add(Q.APC1_50_q);
                columns.add(Q.C1_50_q);
                columns.add(Q.C1_50nz_q);
                columns.add(Q.POC_0_q);
                columns.add(Q.POC_q);
                break;

            case AVERAGE_SHOW_POSITION_2_3:
                columns.add(Q.S2_3_q);
                columns.add(Q.S2_3nz_q);
                columns.add(Q.APS2_3_q);
                columns.add(Q.POS2_3_0_q);
                columns.add(Q.POS2_3_q);
                break;

            case AVERAGE_CLICK_POSITION_2_3:
                columns.add(Q.C2_3_q);
                columns.add(Q.C2_3nz_q);
                columns.add(Q.APC2_3_q);
                columns.add(Q.POC2_3_0_q);
                columns.add(Q.POC2_3_q);
                break;

            case AVERAGE_SHOW_POSITION_4_10:
                columns.add(Q.S4_10_q);
                columns.add(Q.S4_10nz_q);
                columns.add(Q.APS4_10_q);
                columns.add(Q.POS4_10_0_q);
                columns.add(Q.POS4_10_q);
                break;

            case AVERAGE_CLICK_POSITION_4_10:
                columns.add(Q.C4_10_q);
                columns.add(Q.C4_10nz_q);
                columns.add(Q.APC4_10_q);
                columns.add(Q.POC4_10_0_q);
                columns.add(Q.POC4_10_q);
                break;

            case AVERAGE_SHOW_POSITION_11_50:
                columns.add(Q.S11_50_q);
                columns.add(Q.S11_50nz_q);
                columns.add(Q.APS11_50_q);
                columns.add(Q.POS11_50_0_q);
                columns.add(Q.POS11_50_q);
                break;

            case AVERAGE_CLICK_POSITION_11_50:
                columns.add(Q.C11_50_q);
                columns.add(Q.C11_50nz_q);
                columns.add(Q.APC11_50_q);
                columns.add(Q.POC11_50_0_q);
                columns.add(Q.POC11_50_q);
                break;
        }

        return columns.stream().collect(Collectors.joining(","));
    }

    protected static String getOrderColumnName(QueryIndicator indicator) {
        switch (indicator) {
            case TOTAL_SHOWS_COUNT:
                return F.ST;
            case TOTAL_CLICKS_COUNT:
                return F.CT;
            case TOTAL_CTR:
                return F.CTR;
            case TOTAL_SERPS_COUNT:
                return F.SRP;

            case CLICKS_DYNAMICS:
                return F.CD;

            case SHOWS_COUNT_1:
                return F.S1;
            case SHOWS_COUNT_2_3:
                return F.S2_3;
            case SHOWS_COUNT_4_10:
                return F.S4_10;
            case SHOWS_COUNT_11_50:
                return F.S11_50;

            case CLICKS_COUNT_1:
                return F.C1;
            case CLICKS_COUNT_2_3:
                return F.C2_3;
            case CLICKS_COUNT_4_10:
                return F.C4_10;
            case CLICKS_COUNT_11_50:
                return F.C11_50;

            case CTR_1:
                return F.CTR1;
            case CTR_2_3:
                return F.CTR2_3;
            case CTR_4_10:
                return F.CTR4_10;
            case CTR_11_50:
                return F.CTR11_50;

            case AVERAGE_SHOW_POSITION:
                return F.POS;
            case AVERAGE_SHOW_POSITION_2_3:
                return F.POS2_3;
            case AVERAGE_SHOW_POSITION_4_10:
                return F.POS4_10;
            case AVERAGE_SHOW_POSITION_11_50:
                return F.POS11_50;

            case AVERAGE_CLICK_POSITION:
                return F.POC;
            case AVERAGE_CLICK_POSITION_2_3:
                return F.POC2_3;
            case AVERAGE_CLICK_POSITION_4_10:
                return F.POC4_10;
            case AVERAGE_CLICK_POSITION_11_50:
                return F.POC11_50;
        }

        return "";
    }

    protected static class F {
        protected static final String ST = "ST";
        protected static final String STnz = "STnz";
        protected static final String CT = "CT";
        protected static final String S1_50 = "S1_50";
        protected static final String S1_50nz = "S1_50nz";
        protected static final String C1_50 = "C1_50";
        protected static final String C1_50nz = "C1_50nz";
        protected static final String S1 = "S1";
        protected static final String S1nz = "S1nz";
        protected static final String C1 = "C1";
        protected static final String S2_3 = "S2_3";
        protected static final String S2_3nz = "S2_3nz";
        protected static final String C2_3 = "C2_3";
        protected static final String C2_3nz = "C2_3nz";
        protected static final String S4_10 = "S4_10";
        protected static final String S4_10nz = "S4_10nz";
        protected static final String C4_10 = "C4_10";
        protected static final String C4_10nz = "C4_10nz";
        protected static final String S11_50 = "S11_50";
        protected static final String S11_50nz = "S11_50nz";
        protected static final String C11_50 = "C11_50";
        protected static final String C11_50nz = "C11_50nz";
        protected static final String APS2_3 = "APS2_3";
        protected static final String APC2_3 = "APC2_3";
        protected static final String APS4_10 = "APS4_10";
        protected static final String APC4_10 = "APC4_10";
        protected static final String APS11_50 = "APS11_50";
        protected static final String APC11_50 = "APC11_50"; //
        protected static final String CD = "CD";             // Click dynamics

        protected static final String APS1_50 = "APS1_50";
        protected static final String APC1_50 = "APC1_50";

        protected static final String CTR = "CTR";
        protected static final String CTR1 = "CTR1";
        protected static final String CTR2_3 = "CTR2_3";
        protected static final String CTR4_10 = "CTR4_10";
        protected static final String CTR11_50 = "CTR11_50";

        protected static final String POS = "POS";
        protected static final String POS_0 = "POS_0";
        protected static final String POS2_3 = "POS2_3";
        protected static final String POS2_3_0 = "POS2_3_0";
        protected static final String POS4_10 = "POS4_10";
        protected static final String POS4_10_0 = "POS4_10_0";
        protected static final String POS11_50 = "POS11_50";
        protected static final String POS11_50_0 = "POS11_50_0";
        protected static final String POC = "POC";
        protected static final String POC_0 = "POC_0";
        protected static final String POC2_3 = "POC2_3";
        protected static final String POC2_3_0 = "POC2_3_0";
        protected static final String POC4_10 = "POC4_10";
        protected static final String POC4_10_0 = "POC4_10_0";
        protected static final String POC11_50 = "POC11_50";
        protected static final String POC11_50_0 = "POC11_50_0";

        protected static final String SRP = "SRP";
    }

    protected static final class Q {
        protected static final String ST_q = "(sum(shows_1 + shows_2_3 + shows_4_10 + shows_11_50)) as " + F.ST;
        protected static final String STnz_q = "(" + F.ST + " > 0 ? " + F.ST + " : 1) as " + F.STnz;
        protected static final String CT_q = "(sum(clicks_1 + clicks_2_3 + clicks_4_10 + clicks_11_50)) as " + F.CT;
        protected static final String S1_q = "sum(shows_1) as " + F.S1;
        protected static final String S1nz_q = "(" + F.S1 + " > 0 ? " + F.S1 + " : 1) as " + F.S1nz;
        protected static final String C1_q = "sum(clicks_1) as " + F.C1;
        protected static final String S2_3_q = "sum(shows_2_3) as " + F.S2_3;
        protected static final String S2_3nz_q = "(" + F.S2_3 + " > 0 ? " + F.S2_3 + " : 1) as " + F.S2_3nz;
        protected static final String C2_3_q = "sum(clicks_2_3) as " + F.C2_3;
        protected static final String C2_3nz_q = "(" + F.C2_3 + " > 0 ? " + F.C2_3 + " : 1) as " + F.C2_3nz;
        protected static final String S4_10_q = "sum(shows_4_10) as " + F.S4_10;
        protected static final String S4_10nz_q = "(" + F.S4_10 + " > 0 ? " + F.S4_10 + " : 1) as " + F.S4_10nz;
        protected static final String C4_10_q = "sum(clicks_4_10) as " + F.C4_10;
        protected static final String C4_10nz_q = "(" + F.C4_10 + " > 0 ? " + F.C4_10 + " : 1) as " + F.C4_10nz;
        protected static final String S11_50_q = "sum(shows_11_50) as " + F.S11_50;
        protected static final String S11_50nz_q = "(" + F.S11_50 + " > 0 ? " + F.S11_50 + " : 1) as " + F.S11_50nz;
        protected static final String C11_50_q = "sum(clicks_11_50) as " + F.C11_50;
        protected static final String C11_50nz_q = "(" + F.C11_50 + " > 0 ? " + F.C11_50 + " : 1) as " + F.C11_50nz;
        protected static final String APS2_3_q = "sum(agr_pos_shows_2_3) as " + F.APS2_3;
        protected static final String APC2_3_q = "sum(agr_pos_clicks_2_3) as " + F.APC2_3;
        protected static final String APS4_10_q = "sum(agr_pos_shows_4_10) as " + F.APS4_10;
        protected static final String APC4_10_q = "sum(agr_pos_clicks_4_10) as " + F.APC4_10;
        protected static final String APS11_50_q = "sum(agr_pos_shows_11_50) as " + F.APS11_50;
        protected static final String APC11_50_q = "sum(agr_pos_clicks_11_50) as " + F.APC11_50;
        protected static final String CD_PATTERN = "sumIf(clicks_1 + clicks_2_3 + clicks_4_10 + clicks_11_50, %1$s) - sumIf(clicks_1 + clicks_2_3 + clicks_4_10 + clicks_11_50, not(%1$s)) as " + F.CD;

        protected static final String APS1_50_q = "(" + F.S1 + " + " + F.APS2_3 + " + " + F.APS4_10 + " + " + F.APS11_50 + ") as " + F.APS1_50;
        protected static final String APC1_50_q = "(" + F.C1 + " + " + F.APC2_3 + " + " + F.APC4_10 + " + " + F.APC11_50 + ") as " + F.APC1_50;

        protected static final String S1_50_q = "(" + F.S1 + " + " + F.S2_3 + " + " + F.S4_10 + " + " + F.S11_50 + ") as " + F.S1_50;
        protected static final String S1_50nz_q = "(" + F.S1_50 + " > 0 ? " + F.S1_50 + " : 1) as " + F.S1_50nz;
        protected static final String C1_50_q = "(" + F.C1 + " + " + F.C2_3 + " + " + F.C4_10 + " + " + F.C11_50 + ") as " + F.C1_50;
        protected static final String C1_50nz_q = "(" + F.C1_50 + " > 0 ? " + F.C1_50 + " : 1) as " + F.C1_50nz;

        protected static final String CTR_q = "(toFloat32(" + F.CT + ") / " + F.STnz + " ) as " + F.CTR;
        protected static final String CTR1_q = "(toFloat32(" + F.C1 + ") / " + F.S1nz + ") as " + F.CTR1;
        protected static final String CTR2_3_q = "(toFloat32(" + F.C2_3 + ") / " + F.S2_3nz + ") as " + F.CTR2_3;
        protected static final String CTR4_10_q = "(toFloat32(" + F.C4_10 + ") / " + F.S4_10nz + ") as " + F.CTR4_10;
        protected static final String CTR11_50_q = "(toFloat32(" + F.C11_50 + ") / " + F.S11_50nz + ") as " + F.CTR11_50;

        protected static final String POS_0_q = "(toFloat32(" + F.APS1_50 + ") / " + F.S1_50nz + ") as " + F.POS_0;
        protected static final String POS_q = "(" + F.POS_0 + " > 0 ? " + F.POS_0 + " : 50) as " + F.POS;
        protected static final String POS2_3_0_q = "(toFloat32(" + F.APS2_3 + ") / " + F.S2_3nz + ") as " + F.POS2_3_0;
        protected static final String POS2_3_q = "(" + F.POS2_3_0 + " > 0 ? " + F.POS2_3_0 + " : 50) as " + F.POS2_3;
        protected static final String POS4_10_0_q = "(toFloat32(" + F.APS4_10 + ") / " + F.S4_10nz + ") as " + F.POS4_10_0;
        protected static final String POS4_10_q = "(" + F.POS4_10_0 + " > 0 ? " + F.POS4_10_0 + " : 50) as " + F.POS4_10;
        protected static final String POS11_50_0_q = "(toFloat32(" + F.APS11_50 + ") / " + F.S11_50nz + ") as " + F.POS11_50_0;
        protected static final String POS11_50_q = "(" + F.POS11_50_0 + " > 0 ? " + F.POS11_50_0 + " : 50) as " + F.POS11_50;
        protected static final String POC_0_q = "(toFloat32(" + F.APC1_50 + ") / " + F.C1_50nz + ") as " + F.POC_0;
        protected static final String POC_q = "(" + F.POC_0 + " > 0 ? " + F.POC_0 + " : 50) as " + F.POC;
        protected static final String POC2_3_0_q = "(toFloat32(" + F.APC2_3 + ") / " + F.C2_3nz + ") as " + F.POC2_3_0;
        protected static final String POC2_3_q = "(" + F.POC2_3_0 + " > 0 ? " + F.POC2_3_0 + " : 50) as " + F.POC2_3;
        protected static final String POC4_10_0_q = "(toFloat32(" + F.APC4_10 + ") / " + F.C4_10nz + ") as " + F.POC4_10_0;
        protected static final String POC4_10_q = "(" + F.POC4_10_0 + " > 0 ? " + F.POC4_10_0 + " : 50) as " + F.POC4_10;
        protected static final String POC11_50_0_q = "(toFloat32(" + F.APC11_50 + ") / " + F.C11_50nz + ") as " + F.POC11_50_0;
        protected static final String POC11_50_q = "(" + F.POC11_50_0 + " > 0 ? " + F.POC11_50_0 + " : 50) as " + F.POC11_50;

        protected static final String SRP_q = "sum(serps_total) as " + F.SRP;
    }

}
