使用CASE和generate_series()进行查询,命令结果timestamptz下降

时间:2017-08-21 06:48:26

标签: sql postgresql sql-order-by plpgsql set-returning-functions

我是新手,并尝试使用以下代码创建一个函数:

.sequelizerc

上述查询的结果是:

CREATE OR REPLACE FUNCTION public.get_bulan()
returns table (request_detail timestamp with time zone)
language plpgsql stable
as $function$
        begin
        return query

        select
        case
        when (extract(DAY FROM now()) >= 25) then generate_series(date_trunc('year', now()), date_trunc('day', now()) ,interval '1 month')
        when (select extract(month FROM now()) = 2) then now() - (interval '1' month * generate_series(0,1))
        when (select extract(month FROM now()) = 1) then now() - (interval '1' month * generate_series(0,2))
        else generate_series((select date(date_trunc('year', now()))), (select date(now())-'1 month'::interval), interval '1 month')
        end
        order by timetstamptz(request_detail) desc;
        end;
        $function$;

我尝试使用2017-01-01 00:00:00 2017-02-01 00:00:00 2017-03-01 00:00:00 2017-04-01 00:00:00 2017-05-01 00:00:00 2017-06-01 00:00:00 2017-07-01 00:00:00 order by desc,但它不起作用。我想通过降序来下订单,所以我得到2017-07-01到2017-01-01的结果。我该怎么做?

3 个答案:

答案 0 :(得分:2)

您有两种方法可以做到这一点:

  1. 添加as result_timestamp order by result_timestamp desc;

    CREATE OR REPLACE FUNCTION public.get_bulan()
     returns table (request_detail timestamp with time zone)
     language plpgsql stable
     as $function$
        begin
        return query
    
        select 
        case
        when (extract(DAY FROM now()) >= 25) then generate_series(date_trunc('year', now()), date_trunc('day', now()) ,interval '1 month')
        when (select extract(month FROM now()) = 2) then now() - (interval '1' month * generate_series(0,1))
        when (select extract(month FROM now()) = 1) then now() - (interval '1' month * generate_series(0,2))
        else generate_series((select date(date_trunc('year', now()))), (select date(now())-'1 month'::interval), interval '1 month')
        end as result_timestamp order by result_timestamp desc;
    
        end;
        $function$;
    
  2. 或者,当您从其他地方调用时,您可以从过程和顺序中删除排序:

    CREATE OR REPLACE FUNCTION public.get_bulan()
    returns table (request_detail timestamp with time zone)
    language plpgsql stable
    as $function$
            begin
            return query
    
            select 
            case
            when (extract(DAY FROM now()) >= 25) then generate_series(date_trunc('year', now()), date_trunc('day', now()) ,interval '1 month')
            when (select extract(month FROM now()) = 2) then now() - (interval '1' month * generate_series(0,1))
            when (select extract(month FROM now()) = 1) then now() - (interval '1' month * generate_series(0,2))
            else generate_series((select date(date_trunc('year', now()))), (select date(now())-'1 month'::interval), interval '1 month')
            end;
    
            end;
            $function$;
    
  3. 并致电:

    select request_detail from public.get_bulan() order by request_detail desc
    

    注意:第二个很柔韧,你可以轻松操控。

答案 1 :(得分:1)

 select
        (case 
        when (extract(DAY FROM now()) >= 25) then generate_series(date_trunc('year', now()), date_trunc('day', now()) ,interval '1 month')
        when (select extract(month FROM now()) = 2) then now() - (interval '1' month * generate_series(0,1))
        when (select extract(month FROM now()) = 1) then now() - (interval '1' month * generate_series(0,2))
        else generate_series((select date(date_trunc('year', now()))), (select date(now())-'1 month'::interval), interval '1 month')
        end) as time_st  order by time_st desc

输出:

2017-07-01 00:00:00+05:30
2017-06-01 00:00:00+05:30
2017-05-01 00:00:00+05:30
2017-04-01 00:00:00+05:30
2017-03-01 00:00:00+05:30
2017-02-01 00:00:00+05:30
2017-01-01 00:00:00+05:30

答案 2 :(得分:1)

SQL CASE语句的第一个和最后一个分支按降序返回行,其他两个按升序返回。因此,您需要在ORDER BY外部使用其他SELECT

干净的修复方法是让所有4个分支以相同的顺序返回行。

或者更确切地说,完全重写这个以解开混乱:

SELECT *
FROM   generate_series(
         CASE
            WHEN extract(DAY   FROM now()) >= 25 THEN date_trunc('month', now())
            WHEN extract(MONTH FROM now()) <=  2 THEN now()
            ELSE                                      now() - interval '1 month'
         END
       , date_trunc('year' , now())
       , interval '- 1 month'  -- negative interval
      ) t(request_detail)
ORDER  BY request_detail DESC;  -- redundant

负间隔自动生成降序。您可以添加ORDER BY request_detail DESC以使其清晰并更正标准SQL。

如果您愿意,可以将查询包装到函数中。

最重要的是, 不会 generate_series()语句中包含像CASE这样的集合返回函数。这从来都不是一个好主意,但从Postgres 10开始,它会引发一个错误:

ERROR:  set-returning functions are not allowed in CASE

演示:

dbfiddle here