【问题标题】:Use a function to handle a negative offset使用函数处理负偏移
【发布时间】:2014-05-23 19:23:29
【问题描述】:

我正在创建一个 Postgresql 函数来处理负偏移量。当偏移量为负时,我的函数应该返回 0。但是,当我尝试运行此函数时,“行”附近有一个错误,我不知道为什么。我的条件分支出了什么问题?

CREATE OR REPLACE FUNCTION 
    calc_offset(row integer, padding integer) RETURNS integer AS $$
    BEGIN
        if (row-1-padding) < 0 then return 0;
        else return (row-1-padding);
    END;
$$ LANGUAGE plpgsql;

WITH all_the_trimmings AS (
    SELECT ui.id, ui.name, ui.time, 
           row_number() over(order by name asc) as rownumber
    FROM user_infos ui

  ), my_row AS (
    SELECT * FROM all_the_trimmings WHERE id=1
  ), the_slice AS (
    SELECT * FROM all_the_trimmings LIMIT 5 
       OFFSET calc_offset((SELECT rownumber FROM my_row)::int,2)
  )
SELECT * from my_row
UNION ALL
SELECT * from the_slice;

SQL fiddle for the full picture

【问题讨论】:

    标签: sql function postgresql offset plpgsql


    【解决方案1】:

    您的函数calc_offset() 可以替换为这个简单的SQL 函数:

    CREATE OR REPLACE FUNCTION calc_offset(p_row int, padding int)
      RETURNS int AS 'SELECT GREATEST ($1 - $2 - 1, 0)' LANGUAGE sql;
    

    而且你根本不需要函数。只需将GREATEST 与子选择一起使用:

    WITH all_the_trimmings AS (
       SELECT ui.id, ui.name, ui.time, row_number()  OVER (ORDER BY name) AS rn
       FROM   user_infos ui
       )
    , my_row AS (
       SELECT * FROM all_the_trimmings WHERE id=1
       )
    SELECT * FROM my_row
    UNION ALL
    SELECT * FROM all_the_trimmings LIMIT 5 
    OFFSET GREATEST ((SELECT rn - 3 FROM my_row), 0);
    

    或者更简单:

    WITH cte AS (
       SELECT ui.id, ui.name, ui.time, row_number() OVER (ORDER BY name) AS rn
       FROM   user_infos ui
       )
    SELECT * FROM cte WHERE id = 1
    UNION ALL
    SELECT * FROM cte LIMIT 5 
    OFFSET GREATEST ((SELECT rn - 3 FROM cte WHERE id = 1), 0);
    

    SQL Fiddle showing both.

    【讨论】:

      【解决方案2】:

      row 参数是保留字。尝试用其他名称替换它。如果;

      CREATE OR REPLACE FUNCTION
          calc_offset(p_row integer, padding integer) RETURNS integer AS $$
          BEGIN
              if (p_row-1-padding) < 0 then 
                return 0;
              else
                return (p_row-1-padding);
              end if;
          END;
      $$ LANGUAGE plpgsql;
      

      【讨论】:

      • 感谢您的快速回复。我添加了您的代码,但出现新错误。关于 begin 和 $$ 附近未加引号的字符串。 See the error here
      • 所以看起来有时两个 $$ 之间的东西需要在一行上完成。我把那个条件语句写成一行,它似乎工作正常。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多