Thread: SELECT Question
Hi, I have a column with a sequence in a table and want to allocate the first 200 for special purpose thus starting the sequence from 200. For the first 200 I have entries that will be added and removed. Is there an easy way to write a select statement that returns me the frist free number or any within the range of 200? For example if 1-30, and 32-50 are occupied then i would like to fill in the new entry with id 31. I currently do it with a function but I was just wondering if there is a way without it.. Thanks Alex
> Is there an easy way to write a select statement that returns me the > frist free number or any within the range of 200? > For example if 1-30, and 32-50 are occupied then i would like to fill in > the new entry with id 31. > I currently do it with a function but I was just wondering if there is a > way without it.. If I understand well, what something about SELECT min(xxx) FROM table WHERE xxx<50 Best regards, Lada 'Ray' Lostak Unreal64 Develop group http://www.orcave.com http://www.unreal64.net -------------------------------------------------------------------------- In the 1960s you needed the power of two C64s to get a rocket to the moon. Now you need a machine which is a vast number of times more powerful just to run the most popular GUI.
Thanks, but that only gives me smallest number of the ones in use but not the first free number. Alex Lada 'Ray' Lostak wrote: >>Is there an easy way to write a select statement that returns me the >>frist free number or any within the range of 200? >>For example if 1-30, and 32-50 are occupied then i would like to fill in >>the new entry with id 31. >>I currently do it with a function but I was just wondering if there is a >>way without it.. >> >> >If I understand well, what something about > > SELECT min(xxx) FROM table WHERE xxx<50 > >Best regards, >Lada 'Ray' Lostak >Unreal64 Develop group >http://www.orcave.com >http://www.unreal64.net > > >-------------------------------------------------------------------------- >In the 1960s you needed the power of two C64s to get a rocket >to the moon. Now you need a machine which is a vast number >of times more powerful just to run the most popular GUI. > > > > > >
> > Is there an easy way to write a select statement that returns me the > > frist free number or any within the range of 200? > > For example if 1-30, and 32-50 are occupied then i would like to fill in > > the new entry with id 31. > > I currently do it with a function but I was just wondering if there is a > > way without it.. > If I understand well, what something about > > SELECT min(xxx) FROM table WHERE xxx<50 > After I sent it, I saw I understand bad... Just woke up... Sorry :) I personally think, you need small procedure do to that, because you want to perform condition 'min(xxx)' on "unexisting" columns. R.
yes i am doing it that way now, but though there may be another way ... more out of curiosity thanks anyway Lada 'Ray' Lostak wrote: >>>Is there an easy way to write a select statement that returns me the >>>frist free number or any within the range of 200? >>>For example if 1-30, and 32-50 are occupied then i would like to fill in >>>the new entry with id 31. >>>I currently do it with a function but I was just wondering if there is a >>>way without it.. >>> >>> >>If I understand well, what something about >> >> SELECT min(xxx) FROM table WHERE xxx<50 >> >> >> >After I sent it, I saw I understand bad... Just woke up... Sorry :) > >I personally think, you need small procedure do to that, because you want to >perform condition 'min(xxx)' on "unexisting" columns. > >R. > > >---------------------------(end of broadcast)--------------------------- >TIP 7: don't forget to increase your free space map settings > > > >
On Thu, 20 Nov 2003, Alex wrote: > >>Is there an easy way to write a select statement that returns me the > >>frist free number or any within the range of 200? > >>For example if 1-30, and 32-50 are occupied then i would like to fill in > >>the new entry with id 31. If you had a table with an id column and 200 rows 1-200 you could do SELECT MIN(idtab.id) FROM idtab LEFT JOIN realtab ON (idtab.id = realtab.id AND realtab.id IS NULL) A useful generic function would be one something like range(min,max) that would return a set of rows so you wouldn't have to actually have a table. Kris Jurka
On Thu, 20 Nov 2003 16:52:37 +0900, Alex <alex@meerkatsoft.com> wrote: >>>>Is there an easy way to write a select statement that returns me the >>>>frist free number or any within the range of 200? >>>>For example if 1-30, and 32-50 are occupied then i would like to fill in >>>>the new entry with id 31. Fortunately this is not the performance mailing list :-) First free number: SELECT max(t1.id) + 1 FROM t AS t1 INNER JOIN t AS t2 ON (t1.id < 200 AND t1.id < t2.id AND t2.id <= 200) GROUP BY t2.id HAVING max(t1.id) + 1 < t2.id ORDER BY t2.id LIMIT 1; Make sure that there is always a row with id=0 and a row with id=200. Any free number: SELECT id - 1 FROM t WHERE 1 < id AND id <= 200 AND NOT EXISTS (SELECT * FROM t AS t2 WHERE t2.id = t.id - 1) LIMIT 1; Always having a row with id=200 helps avoid unwanted corner cases. One more: SELECT coalesce(max(id), 0) + 1 FROM t WHERE id <= 200 AND id = (SELECT count(*) FROM t AS t2 WHERE t2.id <= t.id); This should work without any dummy rows. And it will not work, if id is not unique or there is any row with id < 1. Servus Manfred
Kris Jurka wrote: > A useful generic function would be one something like range(min,max) that > would return a set of rows so you wouldn't have to actually have a table. > You mean like this? CREATE OR REPLACE FUNCTION test(int,int) RETURNS SETOF int AS ' BEGIN FOR i IN $1..$2 LOOP RETURN NEXT i; END LOOP; RETURN; END; ' LANGUAGE 'plpgsql' STRICT IMMUTABLE; regression=# select * from test(4, 8); test ------ 4 5 6 7 8 (5 rows) HTH, Joe
Joe Conway <mail@joeconway.com> writes: > Kris Jurka wrote: >> A useful generic function would be one something like range(min,max) that >> would return a set of rows so you wouldn't have to actually have a table. > You mean like this? > CREATE OR REPLACE FUNCTION test(int,int) RETURNS SETOF int AS ' > BEGIN > FOR i IN $1..$2 LOOP > RETURN NEXT i; > END LOOP; > RETURN; > END; > ' LANGUAGE 'plpgsql' STRICT IMMUTABLE; I was thinking of proposing that we provide something just about like that as a standard function (written in C, not in plpgsql, so that it would be available whether or not you'd installed plpgsql). There are some places in the information_schema that desperately need it --- right now, the value of FUNC_MAX_ARGS is effectively hard-wired into some of the information_schema views, which means they are broken if one changes that #define. We could fix this if we had a function like the above and exported FUNC_MAX_ARGS as a read-only GUC variable. regards, tom lane
Tom Lane wrote: > Joe Conway <mail@joeconway.com> writes: >>CREATE OR REPLACE FUNCTION test(int,int) RETURNS SETOF int AS ' >>BEGIN >> FOR i IN $1..$2 LOOP >> RETURN NEXT i; >> END LOOP; >> RETURN; >>END; >>' LANGUAGE 'plpgsql' STRICT IMMUTABLE; > > I was thinking of proposing that we provide something just about like > that as a standard function (written in C, not in plpgsql, so that it > would be available whether or not you'd installed plpgsql). There are > some places in the information_schema that desperately need it --- > right now, the value of FUNC_MAX_ARGS is effectively hard-wired into > some of the information_schema views, which means they are broken if > one changes that #define. We could fix this if we had a function like > the above and exported FUNC_MAX_ARGS as a read-only GUC variable. I've been really busy on other-than-postgres stuff lately, but I'm planning to carve out time next week to start doing some 7.5 development. I'll take this one if you want. Joe
All, thanks for the many suggestions Alex Manfred Koizar wrote: >On Thu, 20 Nov 2003 16:52:37 +0900, Alex <alex@meerkatsoft.com> wrote: > > >>>>>Is there an easy way to write a select statement that returns me the >>>>>frist free number or any within the range of 200? >>>>>For example if 1-30, and 32-50 are occupied then i would like to fill in >>>>>the new entry with id 31. >>>>> >>>>> > >Fortunately this is not the performance mailing list :-) > >First free number: >SELECT max(t1.id) + 1 > FROM t AS t1 INNER JOIN t AS t2 > ON (t1.id < 200 AND t1.id < t2.id AND t2.id <= 200) > GROUP BY t2.id >HAVING max(t1.id) + 1 < t2.id > ORDER BY t2.id > LIMIT 1; > >Make sure that there is always a row with id=0 and a row with id=200. > >Any free number: >SELECT id - 1 > FROM t > WHERE 1 < id AND id <= 200 > AND NOT EXISTS (SELECT * FROM t AS t2 WHERE t2.id = t.id - 1) > LIMIT 1; > >Always having a row with id=200 helps avoid unwanted corner cases. > >One more: >SELECT coalesce(max(id), 0) + 1 > FROM t > WHERE id <= 200 > AND id = (SELECT count(*) FROM t AS t2 WHERE t2.id <= t.id); > >This should work without any dummy rows. And it will not work, if id >is not unique or there is any row with id < 1. > >Servus > Manfred > > > >
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Am Thursday 20 November 2003 08:32 schrieben Sie: > > Is there an easy way to write a select statement that returns me the > > frist free number or any within the range of 200? As long as the set of numbers is not too big, the following might work: CREATE TABLE legal_numbers ( num int ); INSERT INTO into legal_numbers VALUES ( 1 ); ... do this with values from 1 to 200; You can create this table once and for all. Now the select is rather simple: SELECT min(num) FROM legal_numbers WHERE num not in ( SELECT id FROM other_table ) ; Mit freundlichem Gruß / With kind regards Holger Klawitter - -- info@klawitter.de -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2 (GNU/Linux) iD8DBQE/vIha1Xdt0HKSwgYRAtGbAJ4xR+Naws0vHugt40GH+BJYY/3bAwCdG7t6 2ijqnA8Fm5Z8h4Zhw5H7p3s= =xsBO -----END PGP SIGNATURE-----