NULLS LAST在CASE的ORDER BY中不起作用

时间:2019-06-18 06:12:47

标签: postgresql

我遇到了奇怪的问题。

这是PostgreSQL函数:

CREATE FUNCTION public.search_companies_ordered(name character varying DEFAULT NULL::character varying, "categoryIds" integer[] DEFAULT NULL::integer[], "cityIds" integer[] DEFAULT NULL::integer[], departments public.department[] DEFAULT NULL::public.department[], "stockTemperatures" public.stock_temperature[] DEFAULT NULL::public.stock_temperature[], "order" public.search_companies_order DEFAULT 'createdAt'::public.search_companies_order, order_type public.order_type DEFAULT 'desc'::public.order_type) RETURNS SETOF public.company
      LANGUAGE plpgsql STABLE
      AS $$
        begin
          IF "search_companies_ordered"."order_type" = 'asc'::order_type THEN
            return query
            SELECT * FROM "search_companies"(
              name                := search_companies_ordered."name",
              "categoryIds"       := search_companies_ordered."categoryIds",
              "cityIds"           := search_companies_ordered."cityIds",
              departments         := search_companies_ordered.departments,
              "stockTemperatures" := search_companies_ordered."stockTemperatures"
            ) AS c
            ORDER BY (
              CASE WHEN "search_companies_ordered"."order" = 'id'::search_companies_order THEN
                c."id"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'name'::search_companies_order THEN
                c."name"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'createdAt'::search_companies_order THEN
                c."createdAt"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'updatedAt'::search_companies_order THEN
                c."updatedAt"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'lastCommentAt'::search_companies_order THEN
                c."lastCommentAt"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'commentsCount'::search_companies_order THEN
                c."commentsCount"
              END
            ) ASC NULLS LAST;
          ELSE
            return query
            SELECT * FROM "search_companies"(
              name                := search_companies_ordered."name",
              "categoryIds"       := search_companies_ordered."categoryIds",
              "cityIds"           := search_companies_ordered."cityIds",
              departments         := search_companies_ordered.departments,
              "stockTemperatures" := search_companies_ordered."stockTemperatures"
            ) AS c
            ORDER BY (
              CASE WHEN "search_companies_ordered"."order" = 'id'::search_companies_order THEN
                c."id"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'name'::search_companies_order THEN
                c."name"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'createdAt'::search_companies_order THEN
                c."createdAt"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'updatedAt'::search_companies_order THEN
                c."updatedAt"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'lastCommentAt'::search_companies_order THEN
                c."lastCommentAt"
              END,
              CASE WHEN "search_companies_ordered"."order" = 'commentsCount'::search_companies_order THEN
                c."commentsCount"
              END
            ) DESC NULLS LAST;
          END IF;
          return;
        end;
        $$;

NULLS LAST之外的所有其他方法都不会对结果记录的顺序产生任何影响。

我尝试省略ORDER BY中的括号–无效:

ORDER BY
  CASE WHEN "search_companies_ordered"."order" = 'id'::search_companies_order THEN
    c."id"
  END,
  CASE WHEN "search_companies_ordered"."order" = 'name'::search_companies_order THEN
    c."name"
  END,
  CASE WHEN "search_companies_ordered"."order" = 'createdAt'::search_companies_order THEN
    c."createdAt"
  END,
    CASE WHEN "search_companies_ordered"."order" = 'updatedAt'::search_companies_order THEN
    c."updatedAt"
  END,
  CASE WHEN "search_companies_ordered"."order" = 'lastCommentAt'::search_companies_order THEN
    c."lastCommentAt"
  END,
  CASE WHEN "search_companies_ordered"."order" = 'commentsCount'::search_companies_order THEN
    c."commentsCount"
  END
ASC NULLS LAST;

search_companies函数如下:

CREATE FUNCTION public.search_companies(name character varying DEFAULT NULL::character varying, "categoryIds" integer[] DEFAULT NULL::integer[], "cityIds" integer[] DEFAULT NULL::integer[], departments public.department[] DEFAULT NULL::public.department[], "stockTemperatures" public.stock_temperature[] DEFAULT NULL::public.stock_temperature[]) RETURNS SETOF public.company
    LANGUAGE sql STABLE
    AS $$
        SELECT DISTINCT ON (c."id")
          c.*
        FROM
          public.company AS c
        LEFT JOIN
          "companyCities" cC ON c.id = cC."companyId"
        LEFT JOIN
          "companyCategories" cCat ON c.id = cCat."companyId"
        LEFT JOIN
          "companyVisit" cv ON c.id = cv."companyId"
        WHERE (
          CASE WHEN "search_companies"."name" is not null THEN
            c.name ILIKE "search_companies"."name"
          ELSE true END
        ) AND (
          CASE WHEN "search_companies"."cityIds" is not null THEN
            "search_companies"."cityIds" @> array[cC."cityId"]
          ELSE true END
        ) AND (
          CASE WHEN "search_companies"."categoryIds" is not null THEN
            "search_companies"."categoryIds" @> array[cCat."categoryId"]
          ELSE true END
        ) AND (
          CASE WHEN "search_companies"."departments" is not null THEN
            "search_companies"."departments" @> array[cCat.department]
          ELSE true END
        ) AND (
          CASE WHEN "search_companies"."stockTemperatures" is not null THEN
            c."stockTemperatures" && "search_companies"."stockTemperatures"
          ELSE true END
        )
        ORDER BY c."id";
      $$;

功能search_companies正常工作。

select id, name, "lastCommentAt" from search_companies() order by "lastCommentAt" desc nulls last limit 100;

问题出在哪里?

2 个答案:

答案 0 :(得分:1)

您要尽早结束案例,这会创建多个案例,并且不适用于order by

代替:

ORDER BY (
          CASE WHEN "search_companies_ordered"."order" = 'id'::search_companies_order THEN
            c."id"
          END,
          CASE WHEN "search_companies_ordered"."order" = 'name'::search_companies_order THEN
            c."name"
          END,
          CASE WHEN "search_companies_ordered"."order" = 'createdAt'::search_companies_order THEN
            c."createdAt"
          END,
          CASE WHEN "search_companies_ordered"."order" = 'updatedAt'::search_companies_order THEN
            c."updatedAt"
          END,
          CASE WHEN "search_companies_ordered"."order" = 'lastCommentAt'::search_companies_order THEN
            c."lastCommentAt"
          END,
          CASE WHEN "search_companies_ordered"."order" = 'commentsCount'::search_companies_order THEN
            c."commentsCount"
          END
        ) ASC NULLS LAST;

尝试:

ORDER BY 
          CASE WHEN "search_companies_ordered"."order" = 'id'::search_companies_order THEN
            c."id"
          WHEN "search_companies_ordered"."order" = 'name'::search_companies_order THEN
            c."name"
          WHEN "search_companies_ordered"."order" = 'createdAt'::search_companies_order THEN
            c."createdAt"
          WHEN "search_companies_ordered"."order" = 'updatedAt'::search_companies_order THEN
            c."updatedAt"
          WHEN "search_companies_ordered"."order" = 'lastCommentAt'::search_companies_order THEN
            c."lastCommentAt"
          WHEN "search_companies_ordered"."order" = 'commentsCount'::search_companies_order THEN
            c."commentsCount"
          END
          ASC NULLS LAST;

答案 1 :(得分:0)

ASC / DESCNULLS FIRST / NULLS LAST不会影响ORDER BY子句中的所有(逗号分隔)表达式,只会影响它们所在的那个表达式

所以

... ORDER BY a, b, c DESC NULLS LAST

相同
... ORDER BY a ASC NULLS LAST,
             b ASC NULLS LAST,
             c DESC NULLS LAST

如果您希望所有表达式最后都以NULL降序排列,则必须将DESC NULLS LAST附加到每个ORDER BY表达式中。