Re: interesting sequence

From: Gavin Flower <GavinFlower(at)archidevsys(dot)co(dot)nz>
To: John Fabiani <johnf(at)jfcomputer(dot)com>
Cc: pgsql-sql(at)postgresql(dot)org
Subject: Re: interesting sequence
Date: 2011-07-06 09:47:06
Message-ID: 4E142F1A.8060900@archidevsys.co.nz
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-sql

On 06/07/11 01:52, John Fabiani wrote:
> Hi,
>
> I have a special need to create a sequence like function.
>
> "O-20110704 -2" which is
> "O" for order (there are other types)
> "20110704" is for July 4, 2011
> '2' the second order of the day for July 4, 2011
>
> I of course can get the type and date. What I don't know is how to get is the
> last number. It would seem to be that I would need a loop to determine if the
> next number existed.
>
> LOOP
> --Check to see if the string exist in a table
> -- count = count +1
> -- until I don't find the string
> END LOOP;
>
> but then I thought I could do something like
>
> for $1 in (select string from sometable)
> LOOP
> count = count + 1
>
> or something like this
>
> for i in 1..999 LOOP
> -- check for the existence of the string in a table using 'i'
> -- there will never be 999 orders in one day.
> END LOOP
>
>
> So here is the question what would be the best way for a multi-user system?
> If someone has a better thought - it would be helpful.
>
> BTW I did NOT design the number - in fact it seems silly to me.
>
> Johnf
>
Hi John,

How about using a table to hold the latest sequence for each order type
and date, along with a function to insert a new order?

(I've included the code to test the idea and the results, I am using
9.1beta2, but it should not make any difference - I think!):

DROP TABLE IF EXISTS my_order;
DROP TABLE IF EXISTS order_sequence;

CREATE TABLE my_order
(
order_num text PRIMARY KEY,
payload text
);

CREATE TABLE order_sequence
(
type int,
day date,
seq int NOT NULL,
PRIMARY KEY (type, day)
);

CREATE OR REPLACE FUNCTION create_my_order
(
IN type int,
IN day date,
IN payload text
) RETURNS VOID
AS
$$
DECLARE
v_order_num text;
v_seq_old int;
v_seq_new int;
BEGIN
SELECT
os.seq
FROM
order_sequence os
WHERE
os.type = create_my_order.type AND
os.day = create_my_order.day
INTO
v_seq_old;

IF v_seq_old IS NULL THEN
v_seq_new := 1;
INSERT INTO order_sequence(type, day, seq)
VALUES (type, day, v_seq_new);
ELSE
v_seq_new := v_seq_old + 1;
UPDATE
order_sequence AS os
SET
seq = v_seq_new
WHERE
os.type = create_my_order.type AND
os.day = create_my_order.day;
END IF;

v_order_num := type::text ||
'-' ||
to_char(day, 'YYMMDD') ||
'-' ||
v_seq_new::text;

INSERT INTO my_order(order_num, payload)
VALUES (v_order_num, payload);
END;
$$ LANGUAGE plpgsql
VOLATILE
;

SELECT create_my_order (0, '2010-03-24', 'order #1 details');
SELECT create_my_order (0, '2010-03-24', 'order #2 details');
SELECT create_my_order (0, '2010-06-15', 'order #3 details');
SELECT create_my_order (5, '2010-03-24', 'order #4 details');
SELECT create_my_order (0, '2010-06-15', 'order #5 details');
SELECT create_my_order (3, '2010-06-14', 'order #6 details');

TABLE order_sequence;
TABLE my_order;

////////// This outputs the following:

type | day | seq
------+------------+-----
0 | 2010-03-24 | 2
5 | 2010-03-24 | 1
0 | 2010-06-15 | 2
3 | 2010-06-14 | 1
(4 rows)

order_num | payload
------------+------------------
0-100324-1 | order #1 details
0-100324-2 | order #2 details
0-100615-1 | order #3 details
5-100324-1 | order #4 details
0-100615-2 | order #5 details
3-100614-1 | order #6 details
(6 rows)

In response to

Responses

Browse pgsql-sql by date

  From Date Subject
Next Message Jasen Betts 2011-07-06 12:28:13 Re: interesting sequence
Previous Message Samuel Gendler 2011-07-06 07:04:10 Re: group by with sum and sum till max date