Anton Melser wrote:
> Hi,
> I am trying to move up in the world with my sql and need to do the
> following...
> I have a subscribers table and I need to export to csv (semi-colon
> separated) certain fields - that is fine, but I also need to export a
> multi-select field from another table as one string (0 to n values
> separated by commas) per line. The problem being that to get the
> actual string I have to go via 4 other relations... and as I have
> 200k+ subscribers this takes a while.
200k isn't all that much, unless you have a lot of large columns.
> My idea (which seems to work, though I haven't tested fully as it
> takes too damn long!), was to do the following. I would REALLY
> appreciate any pointers as my sql has never been this challenged!
>
> CREATE OR REPLACE FUNCTION mytest()
> RETURNS integer AS
> $BODY$DECLARE kindy INTEGER;
> BEGIN
> create temporary table tmp_interests(
> id bigint,
> value character varying(100)
> )
> WITHOUT OIDS
> ON COMMIT DROP;
>
> insert into tmp_interests
> select distinct si.subid, rbi.value
> from restem rbi, cats cc, trm_terms tt, subrest si
> where rbi.key = cc.name
> and cc.catid = tt.modcid
> and tt.tid = si.themeid;
You can do these in one go using
CREATE TEMPORARY TABLE tmp_interests AS SELECT ...
> create temporary table tmp_subscribers(
> email character varying(200),
> format character varying(4),
> interests character varying(1000),
> )
> WITHOUT OIDS
> ON COMMIT DROP;
>
> insert into tmp_subscribers
> Select email,
> format,
> my_interests(id) as interests
> from subscriber;
>
> GET DIAGNOSTICS kindy = ROW_COUNT;
>
> copy tmp_subscribers to '/home/myname/subs.csv' WITH CSV DELIMITER AS
> ';' NULL AS '';
If you have PG8.2 and can combine your 2 select queries into one, then
you can create a view of them and copy that instead. It takes out all
the inserts and can use your already existing table statistics - it
should be faster.
Also, after inserting a bunch of records into a table, make a habit of
running ANALYSE on it. Otherwise the query-planner knows nothing about
the data in the tables and is likely to come up with a sub-optimal query
plan.
>
> GET DIAGNOSTICS kindy = ROW_COUNT;
>
> return kindy;
>
> END;$BODY$
> LANGUAGE 'plpgsql' VOLATILE;
>
> ...
>
>
> CREATE OR REPLACE FUNCTION my_interests(bigint)
> RETURNS character varying AS
> $BODY$DECLARE
> subid ALIAS FOR $1;
> interests character varying;
> myinterest RECORD;
>
> BEGIN
> interests := '';
> FOR myinterest IN execute 'select value from tmp_interests where id =
> ' || subid LOOP
No need for a dynamic query here...
> if interests = '' then
> interests := myinterest.value;
> else
> interests := interests || ',' || myinterest.value;
> end if;
> END LOOP;
>
> RETURN interests;
> END$BODY$
> LANGUAGE 'plpgsql' VOLATILE;
I'd have to look up the syntax, but I'm quite certain you can put the
results of a select into an array. After that you can call
array_to_string(...) to convert it into a comma seperated string. That'd
take away the need for this SP (which I think is actually STABLE instead
of VOLATILE).
--
Alban Hertroys
alban@magproductions.nl
magproductions b.v.
T: ++31(0)534346874
F: ++31(0)534346876
M:
I: www.magproductions.nl
A: Postbus 416
7500 AK Enschede
// Integrate Your World //