Обсуждение: [SQL] Issues with lag command
Hello
I have a test table with the following structure (2 columns: ID and time_id )and dataID, time_id
1;"2015-01-01"
2;""
3;""
4;"2015-01-02"
5;""
6;""
7;""
8;"2015-01-03"
9;""
10;""
11;""
12;""
13;"2015-01-05"
14;""
15;""
16;""
I'd like to update line 2 and 3 with the date in record 1 (2015-01-01)2;""
3;""
4;"2015-01-02"
5;""
6;""
7;""
8;"2015-01-03"
9;""
10;""
11;""
12;""
13;"2015-01-05"
14;""
15;""
16;""
CREATE OR REPLACE FUNCTION public.update_test_dates()
RETURNS SETOF test AS
$BODY$
DECLARE
r test%rowtype;
BEGIN
FOR r IN SELECT * FROM test order by id
LOOP
-- can do some processing here
if r.time_id is null
then
update test set time_id= (select lag(time_id) OVER (ORDER BY id) from test where id=r.id) where id=r.id;
end if;
RETURN NEXT r; -- return current row of SELECT
END LOOP;
RETURN;
END
$BODY$
LANGUAGE plpgsql;
select * from update_test_dates();
On Fri, Jul 28, 2017 at 10:48 AM, Mohamed DIA <macdia2002@gmail.com> wrote:
RegardsAny one can tell me what needs to be changed in my procedure in order to fix the issue?However, it does not work. Postgres update all rows with a NULL valueI use the LAG function and the below codeThe general logic is that anytime we find a record with a time_id null, we would like to update it with the previous time_id that is not null.Update line 5,6 and 7 with the date in record 4 (2015-01-02) and so onHelloI have a test table with the following structure (2 columns: ID and time_id )and data
ID, time_id1;"2015-01-01"I'd like to update line 2 and 3 with the date in record 1 (2015-01-01)
2;""
3;""
4;"2015-01-02"
5;""
6;""
7;""
8;"2015-01-03"
9;""
10;""
11;""
12;""
13;"2015-01-05"
14;""
15;""
16;""
CREATE OR REPLACE FUNCTION public.update_test_dates()
RETURNS SETOF test AS
$BODY$
DECLARE
r test%rowtype;
BEGIN
FOR r IN SELECT * FROM test order by id
LOOP
-- can do some processing here
if r.time_id is null
then
update test set time_id= (select lag(time_id) OVER (ORDER BY id) from test where id=r.id) where id=r.id;
end if;
RETURN NEXT r; -- return current row of SELECT
END LOOP;
RETURN;
END
$BODY$
LANGUAGE plpgsql;
select * from update_test_dates();
I may be wrong about this, but doesn't lag need an offset value? So your statement should be `lag(time_id, 1)`?
Maybe lag defaults to offset 1 but if not, then it would seem your current statement is grabbing its own row's time_id, and you want to pull the time_id from the row offset by 1?
Steve
I use the LAG function and the below codeThe general logic is that anytime we find a record with a time_id null, we would like to update it with the previous time_id that is not null.
Lag can be made to work but only if you know that maximum lag that guarantees a non-null value is present. If you cannot pick a reasonable number then you should write a custom aggregate function. I believe I've seen posts (probably to -general) detailing this and you might find it in blog posts or the like as well. I'm unable to provide a working example right now.
David J.
Hello
I have a test table with the following structure (2 columns: ID and time_id )and data
ID, time_id
1;"2015-01-01"
2;""
3;""
4;"2015-01-02"
5;""
6;""
7;""
8;"2015-01-03"
9;""
10;""
11;""
12;""
13;"2015-01-05"
14;""
15;""
16;""
I'd like to update line 2 and 3 with the date in record 1 (2015-01-01)
Update line 5,6 and 7 with the date in record 4 (2015-01-02) and so on
How about simple SQL instead of PlSql:
UPDATE test T1 SET time_id = (SELECT T2.time_id FROM test T2 WHERE T2.id =
(SELECT max(T3.id) FROM test T3 WHERE T3.id < T1.id AND T3.time_id IS NOT NULL)
)
WHERE T1.time_id IS NULL;
Regards,
Igor Neyman
Igor Neyman <ineyman@perceptron.com> writes: > Hello > I have a test table with the following structure (2 columns: ID and time_id )and data > > ID, time_id > 1;"2015-01-01" > 2;"" > 3;"" > 4;"2015-01-02" > 5;"" > 6;"" > 7;"" > 8;"2015-01-03" > 9;"" > 10;"" > 11;"" > 12;"" > 13;"2015-01-05" > 14;"" > 15;"" > 16;"" > I'd like to update line 2 and 3 with the date in record 1 (2015-01-01) > Update line 5,6 and 7 with the date in record 4 (2015-01-02) and so on > How about simple SQL instead of PlSql: > > UPDATE test T1 SET time_id = (SELECT T2.time_id FROM test T2 WHERE T2.id = > (SELECT max(T3.id) FROM test T3 WHERE T3.id < T1.id AND T3.time_id IS NOT NULL) > ) > WHERE T1.time_id IS NULL; You don't need that many table aliases: UPDATE test SET time_id = ( SELECT T1.time_id FROM test T1 WHERE T1.id < test.id AND T1.time_id IS NOT NULL ORDER BY T1.id DESC LIMIT 1 ) WHERE time_id IS NULL;