PL/pgSQL中奇怪的日期差异问题

发布于 2024-12-10 04:17:36 字数 2325 浏览 0 评论 0原文

我编写了一个程序,应根据每个人的经验天数增加员工表的工资。增加的值在另一个表中。有人能告诉我为什么工作时间超过 3650 天的员工的工资没有增加吗?

DECLARE
   row record;
   row2 record;
   dateDiff int;

BEGIN
  FOR row IN EXECUTE 'SELECT * FROM employee'
  LOOP
     FOR row2 IN SELECT * FROM increases
     LOOP
        dateDiff := now()::date - row.empjoindate;
        IF dateDiff> 3650 THEN
           RAISE NOTICE '%', dateDiff;
        END IF;
        IF dateDiff >= row2.employment_length_from
       AND dateDiff <  row2.employment_length_to THEN 
           UPDATE employee SET empsalary = empsalary + row2.pay_rise WHERE empid = row.empid;
        END IF;
     END LOOP;
  END LOOP;
END;

加薪表如下所示:

 id | employment_length_from | employment_length_to | pay_rise
----+------------------------+----------------------+----------
  2 |                   3650 |                 7300 |      200
  3 |                   7300 |                10950 |      400
  4 |                  10950 |                14600 |      600
  5 |                  14600 |                18250 |      800
  6 |                  18250 |                21900 |     1000
  1 |                      0 |                 3650 |      100

如果有不清楚的地方,请向我提问。

编辑

表定义是: 对于员工:

     Column      |            Type             | Modifiers
-----------------+-----------------------------+-----------
 empid           | integer                     | not null
 empemailaddress | character varying(255)      | not null
 empjoindate     | date                        |
 emplastname     | character varying(255)      |
 emplogintime    | timestamp without time zone |
 empname         | character varying(255)      |
 ispermanent     | boolean                     | not null
 empsalary       | double precision            |

指数:

"employee_pkey" PRIMARY KEY, btree (empid)

对于加薪:

         Column         |       Type       | Modifiers
------------------------+------------------+-----------
 id                     | integer          | not null
 employment_length_from | integer          |
 employment_length_to   | integer          |
 pay_rise               | double precision |

指数:

"increases_pkey" PRIMARY KEY, btree (id)

I have written a procedure that should increase salary for employee table according to days of each persons experience. The values for increase are in another table. Could someone tell me why it doesn't increase salary for employees working more than 3650 days?

DECLARE
   row record;
   row2 record;
   dateDiff int;

BEGIN
  FOR row IN EXECUTE 'SELECT * FROM employee'
  LOOP
     FOR row2 IN SELECT * FROM increases
     LOOP
        dateDiff := now()::date - row.empjoindate;
        IF dateDiff> 3650 THEN
           RAISE NOTICE '%', dateDiff;
        END IF;
        IF dateDiff >= row2.employment_length_from
       AND dateDiff <  row2.employment_length_to THEN 
           UPDATE employee SET empsalary = empsalary + row2.pay_rise WHERE empid = row.empid;
        END IF;
     END LOOP;
  END LOOP;
END;

Table for increasing salaries looks like this:

 id | employment_length_from | employment_length_to | pay_rise
----+------------------------+----------------------+----------
  2 |                   3650 |                 7300 |      200
  3 |                   7300 |                10950 |      400
  4 |                  10950 |                14600 |      600
  5 |                  14600 |                18250 |      800
  6 |                  18250 |                21900 |     1000
  1 |                      0 |                 3650 |      100

If something is not clear just ask me questions.

Edit

The table definitions are:
For Employee:

     Column      |            Type             | Modifiers
-----------------+-----------------------------+-----------
 empid           | integer                     | not null
 empemailaddress | character varying(255)      | not null
 empjoindate     | date                        |
 emplastname     | character varying(255)      |
 emplogintime    | timestamp without time zone |
 empname         | character varying(255)      |
 ispermanent     | boolean                     | not null
 empsalary       | double precision            |

Indexes:

"employee_pkey" PRIMARY KEY, btree (empid)

For increases:

         Column         |       Type       | Modifiers
------------------------+------------------+-----------
 id                     | integer          | not null
 employment_length_from | integer          |
 employment_length_to   | integer          |
 pay_rise               | double precision |

Indexes:

"increases_pkey" PRIMARY KEY, btree (id)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

在梵高的星空下 2024-12-17 04:17:36
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp;

CREATE TABLE tmp.increases
    (id INTEGER NOT NULL PRIMARY KEY
    , employment_length_from INTEGER NOT NULL
    , employment_length_to INTEGER NOT NULL
    , pay_rise double precision
    );
INSERT INTO tmp.increases(id
             ,employment_length_from,employment_length_to,pay_rise)
VALUES
    (1 , 0 , 3650 , 100)
    ,(2 , 3650 , 7300 , 200)
    ,(3 , 7300 , 10950 , 400)
    ,(4 , 10950 , 14600 , 600)
    ,(5 , 14600 , 18250 , 800)
    ,(6 , 18250 , 21900 , 1000)
    ;

CREATE TABLE tmp.employee
    ( empid INTEGER NOT NULL
    , empemailaddress VARCHAR (255) not null
    , empjoindate DATE
    , emplastname VARCHAR (255)
    , emplogintime TIMESTAMP WITHOUT TIME ZONE
    , empname VARCHAR(255)
    , ispermanent BOOLEAN NOT NULL
    , empsalary DOUBLE PRECISION
    );
INSERT INTO tmp.employee(empid,empemailaddress,empjoindate,emplastname,emplogintime,empname,ispermanent,empsalary)
VALUES
(1,'[email protected]' , '1939-01-01', 'Lutser', '2011-09-30' , 'Kleine' , True, 100.0 )
, (2,'[email protected]' , '1949-01-01', 'Prutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (3,'[email protected]' , '1959-01-01', 'Klutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (4,'[email protected]' , '1969-01-01', 'Glutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (5,'[email protected]' , '1979-01-01', 'Brutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (6,'[email protected]' , '1989-01-01', 'Mutser', '2011-10-01' , 'Grote' , True, 200.0 )
    ;

SELECT * FROM tmp.employee ;

-- EXPLAIN ANALYZE
UPDATE tmp.employee emp
SET empsalary = empsalary + inc.pay_rise
FROM tmp.increases inc
    WHERE (now() - emp.empjoindate)
          >= inc.employment_length_from * '1 day'::interval
    AND (now() - emp.empjoindate)
         < inc.employment_length_to * '1 day'::interval
    ;
SELECT * FROM tmp.employee ;

区间和整数之间的转换可能会很痛苦。上面我通过将 int 乘以 1 天的间隔解决了这个问题。现在您可以将此片段嵌入到过程/函数中。

DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp;

CREATE TABLE tmp.increases
    (id INTEGER NOT NULL PRIMARY KEY
    , employment_length_from INTEGER NOT NULL
    , employment_length_to INTEGER NOT NULL
    , pay_rise double precision
    );
INSERT INTO tmp.increases(id
             ,employment_length_from,employment_length_to,pay_rise)
VALUES
    (1 , 0 , 3650 , 100)
    ,(2 , 3650 , 7300 , 200)
    ,(3 , 7300 , 10950 , 400)
    ,(4 , 10950 , 14600 , 600)
    ,(5 , 14600 , 18250 , 800)
    ,(6 , 18250 , 21900 , 1000)
    ;

CREATE TABLE tmp.employee
    ( empid INTEGER NOT NULL
    , empemailaddress VARCHAR (255) not null
    , empjoindate DATE
    , emplastname VARCHAR (255)
    , emplogintime TIMESTAMP WITHOUT TIME ZONE
    , empname VARCHAR(255)
    , ispermanent BOOLEAN NOT NULL
    , empsalary DOUBLE PRECISION
    );
INSERT INTO tmp.employee(empid,empemailaddress,empjoindate,emplastname,emplogintime,empname,ispermanent,empsalary)
VALUES
(1,'[email protected]' , '1939-01-01', 'Lutser', '2011-09-30' , 'Kleine' , True, 100.0 )
, (2,'[email protected]' , '1949-01-01', 'Prutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (3,'[email protected]' , '1959-01-01', 'Klutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (4,'[email protected]' , '1969-01-01', 'Glutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (5,'[email protected]' , '1979-01-01', 'Brutser', '2011-10-01' , 'Grote' , True, 200.0 )
, (6,'[email protected]' , '1989-01-01', 'Mutser', '2011-10-01' , 'Grote' , True, 200.0 )
    ;

SELECT * FROM tmp.employee ;

-- EXPLAIN ANALYZE
UPDATE tmp.employee emp
SET empsalary = empsalary + inc.pay_rise
FROM tmp.increases inc
    WHERE (now() - emp.empjoindate)
          >= inc.employment_length_from * '1 day'::interval
    AND (now() - emp.empjoindate)
         < inc.employment_length_to * '1 day'::interval
    ;
SELECT * FROM tmp.employee ;

Casting between intervals and integers can be painful. Above I solved this by multiplying the int with a 1day interval. Now it is up to you to embed this fragment in a procedure / function.

无边思念无边月 2024-12-17 04:17:36

一个简单的 UPDATE 应该可以做到:

UPDATE employee e
SET    empsalary = empsalary + i.pay_rise
FROM   increases i
WHERE  (now()::date - e.empjoindate) >= i.employment_length_from
AND    (now()::date - e.empjoindate)  < i.employment_length_to;

您不需要为此使用 plpgsql 函数。
我建议您在行获得加注时对其进行标记(在同一查询中),这样您就不会意外多次加注。

编辑:

这是一个 plpgsql 函数,按照您的要求执行相同的操作。它返回获得加薪的员工人数。

CREATE OR REPLACE FUNCTION f_raise(OUT happy_employees integer) AS
$BODY$
BEGIN

UPDATE employee e
SET    empsalary = empsalary + i.pay_rise
FROM   increases i
WHERE  (now()::date - e.empjoindate) >= i.employment_length_from
AND    (now()::date - e.empjoindate)  < i.employment_length_to;

GET DIAGNOSTICS happy_employees = ROW_COUNT;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;
COMMENT ON FUNCTION f_raise() IS 'Gives employees who deserve it a raise.
Returns number of happy employees.'

A simple UPDATE should do:

UPDATE employee e
SET    empsalary = empsalary + i.pay_rise
FROM   increases i
WHERE  (now()::date - e.empjoindate) >= i.employment_length_from
AND    (now()::date - e.empjoindate)  < i.employment_length_to;

You don't need a plpgsql function for this.
I would advise you mark rows when they get their raise (in the same query) so you don't raise multiple times by accident.

Edit:

Here is a plpgsql function doing the same, as you asked for it. It returns the number of employees who got a raise.

CREATE OR REPLACE FUNCTION f_raise(OUT happy_employees integer) AS
$BODY$
BEGIN

UPDATE employee e
SET    empsalary = empsalary + i.pay_rise
FROM   increases i
WHERE  (now()::date - e.empjoindate) >= i.employment_length_from
AND    (now()::date - e.empjoindate)  < i.employment_length_to;

GET DIAGNOSTICS happy_employees = ROW_COUNT;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;
COMMENT ON FUNCTION f_raise() IS 'Gives employees who deserve it a raise.
Returns number of happy employees.'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文