Можно ли использовать WHERE по какому-либо условию IF для PostgreSQL? - PullRequest
2 голосов
/ 05 октября 2019

У меня есть следующий запрос SQL для отчета.

select customers."AppId", second_dep "SecondDeps", first_dep "FirstDeps",
       customers_count "Customers", registrations "Registrations"
From (select Count("AppId") as customers_count, "AppId"
      FROM "Customers"
               join "Advertisers" A on "Customers"."AdvertiserId" = A."AdvertiserId"
               join "Categories" C2 on "Customers"."CategoryId" = C2."CategoryId"

      where A."Name" in (:AdvertiserNames)
        AND C2."Name" = :CategoryName
      GROUP BY "AppId"
     ) as customers

         left join

     (select C."AppId", count(CE.*) as second_dep
      from "CustomerEvents" as CE
               inner join "Customers" C on CE."CustomerId" = C."CustomerId"
      WHERE "EventType" = 'deposit'
        and "Again" = TRUE
      GROUP BY C."AppId") as dep2 on customers."AppId" = dep2."AppId"

        left  join

     (select C."AppId", count(CE.*) as first_dep
      from "CustomerEvents" as CE
               inner join "Customers" C on CE."CustomerId" = C."CustomerId"
      WHERE "EventType" = 'deposit'
        and "Again" = false
      GROUP BY C."AppId") as dep on customers."AppId" = dep."AppId"

         left join

     (select C."AppId", count(CE.*) as registrations
      from "CustomerEvents" as CE
               inner join "Customers" C on CE."CustomerId" = C."CustomerId"
      WHERE "EventType" = 'registration'
      GROUP BY C."AppId") as regs on regs."AppId" = customers."AppId";

Строка с проблемой:

where A."Name" in (:AdvertiserNames)

Я хотел бы пропустить ее, если AdvertiserNames пусто. Является ли это возможным? Хорошо, я могу проверить это на стороне кода, но этот путь приведет меня к копированию всего запроса с небольшой разницей (я имею в виду, если AdvertiserNames - пустой запуск SQL без where A."Name" in (:AdvertiserNames)). Или я могу использовать конкатенацию, чтобы получить подходящий SQL. Мне тоже не нравится этот путь.

О моем технологическом стеке. Это .NET Core 2.2 с PostgreSQL. Вот код всего метода отчета:

public IQueryable<ByApplicationsReportModel> ByApplications(string category, List<string> advertisers)
{
    var rawSql = new RawSqlString(@"
        select customers.""AppId"", second_dep ""SecondDeps"", first_dep ""FirstDeps"",
    customers_count ""Customers"", registrations ""Registrations""
            From (select Count(""AppId"") as customers_count, ""AppId""
            FROM ""Customers""
            join ""Advertisers"" A on ""Customers"".""AdvertiserId"" = A.""AdvertiserId""
            join ""Categories"" C2 on ""Customers"".""CategoryId"" = C2.""CategoryId""
            where A.""Name"" in (@AdvertiserNames)
            AND C2.""Name"" = @CategoryName
            GROUP BY ""AppId""
                ) as customers

                left join

                (select C.""AppId"", count(CE.*) as second_dep
                from ""CustomerEvents"" as CE
            inner join ""Customers"" C on CE.""CustomerId"" = C.""CustomerId""
            WHERE ""EventType"" = 'deposit'
            and ""Again"" = TRUE
            GROUP BY C.""AppId"") as dep2 on customers.""AppId"" = dep2.""AppId""

            left  join

                (select C.""AppId"", count(CE.*) as first_dep
                from ""CustomerEvents"" as CE
            inner join ""Customers"" C on CE.""CustomerId"" = C.""CustomerId""
            WHERE ""EventType"" = 'deposit'
            and ""Again"" = false
            GROUP BY C.""AppId"") as dep on customers.""AppId"" = dep.""AppId""

            left join

                (select C.""AppId"", count(CE.*) as registrations
                from ""CustomerEvents"" as CE
            inner join ""Customers"" C on CE.""CustomerId"" = C.""CustomerId""
            WHERE ""EventType"" = 'registration'
            GROUP BY C.""AppId"") as regs on regs.""AppId"" = customers.""AppId""");

    var advertisersParam = new NpgsqlParameter("AdvertiserNames",  
        string.Join(",", advertisers) );

    var categoryParam = new NpgsqlParameter("CategoryName", category);

    return _context.ByApplicationsReportModels
        .FromSql(rawSql, categoryParam, advertisersParam);
}

Есть идеи?

Ответы [ 2 ]

3 голосов
/ 05 октября 2019

Вы можете попробовать изменить where A.""Name"" in (@AdvertiserNames) на where (A.""Name"" in (@AdvertiserNames) or @AdvertiserNames = '').

1 голос
/ 05 октября 2019

Вместо того, чтобы объединять своих рекламодателей в строку, вы можете просто передать массив строк непосредственно в ваш запрос:

var advertisersParam = new NpgsqlParameter("AdvertiserNames", advertisers));

В SQL вместо использования конструкции x IN (@advertisers) вам потребуетсяизмените на x = ANY (@advertisers).

Примечание: вам все равно понадобится дополнительное предложение, если вы хотите, чтобы проверка прошла, когда @advertisers пуст.

...