[SQL] sql query with join and parameter in postgresql function
Hello, I'd like to write a function similar to that: CREATE FUNCTION public.report_join_parameter(char(6)) RETURNS ??? AS ' SELECT tableA.field1, tableA.field2, tableB.field1, tableB.field2, tableC.field1, tableC.field2, FROM tableA INNER JOIN tableB ON tableA.pk = tableB.fk INNER JOIN tableC ON tableB.pk = tableC.fk WHERE tableC.field3= 0 AND tableB.field1= $1 ' LANGUAGE 'sql' VOLATILE; Do I ***HAVE TO*** define a composite type for the columns my function is supposed to return? Isn't there a simpler method, that could allow me to avoid this extra work? I thought a view would be more appropriate, but if I'm not wrong, a view does not accept any parameter as input... Thanks! Philippe ---(end of broadcast)--- TIP 8: explain analyze is your friend
Re: [SQL] sql query with join and parameter in postgresql function
> > I thought a view would be more appropriate, but > > if I'm not wrong, a view does not accept any parameter > > as input... > > But you can just define the view and select it with a WHERE clause with > your parameter, just like a normal table. Would that help? Thanks! That's perfect. I join in a view, and limit in a function, with a WHERE clause. And no need for any redundant composite type, although I agree this is not that complicated to use... Philippe Lang ---(end of broadcast)--- TIP 6: Have you searched our list archives? http://archives.postgresql.org
[SQL] Disable/Enable Trigger?
Hello, How can I disable a trigger in a function, and then enable it again? I'm using PG 7.3.4. Do I have to delete it, and create it again? Thanks Philippe ---(end of broadcast)--- TIP 6: Have you searched our list archives? http://archives.postgresql.org
[SQL] crosstabs
Hello,
I need to do something similar to a cross tabulation, but without any
aggregation.
Here is an example:
-- TABLE DEFINITION
CREATE TABLE public.type
(
code char(1) PRIMARY KEY,
type varchar(30)
) WITHOUT OIDS;
CREATE TABLE public.master
(
id int4 PRIMARY KEY,
master_name varchar(30)
) WITHOUT OIDS;
CREATE TABLE public.detail
(
id int4 PRIMARY KEY,
code_type char(1) REFERENCES public.type,
id_master int4 REFERENCES public.master,
detail_name varchar(30)
) WITHOUT OIDS;
-- DATA
INSERT INTO public.type VALUES('A', 'TA');
INSERT INTO public.type VALUES('B', 'TB');
INSERT INTO public.type VALUES('C', 'TC');
INSERT INTO public.master VALUES(1, 'M1');
INSERT INTO public.master VALUES(2, 'M2');
INSERT INTO public.master VALUES(3, 'M3');
INSERT INTO public.detail VALUES(1, 'A', 1, 'M1, D1');
INSERT INTO public.detail VALUES(2, 'B', 1, 'M1, D2');
INSERT INTO public.detail VALUES(3, 'A', 1, 'M1, D3');
INSERT INTO public.detail VALUES(4, 'C', 1, 'M1, D4');
INSERT INTO public.detail VALUES(5, 'C', 2, 'M2, D1');
INSERT INTO public.detail VALUES(6, 'A', 3, 'M3, D1');
INSERT INTO public.detail VALUES(7, 'A', 3, 'M3, D2');
INSERT INTO public.detail VALUES(8, 'B', 3, 'M3, D3');
INSERT INTO public.detail VALUES(9, 'A', 3, 'M3, D4');
INSERT INTO public.detail VALUES(10, 'B', 3, 'M3, D5');
INSERT INTO public.detail VALUES(11, 'C', 3, 'M3, D6');
INSERT INTO public.detail VALUES(12, 'C', 3, 'M3, D7');
-- QUERY
SELECT
master_name,
detail_name,
type
FROM
master INNER JOIN detail
ON master.id = detail.id_master
INNER JOIN type
ON detail.code_type = type.code
ORDER by master.id, detail.id;
The result of that is:
--
master_name | detail_name | type |
--
M1 | M1, D1 | TA |
M1 | M1, D2 | TB |
M1 | M1, D3 | TA |
M1 | M1, D4 | TC |
M2 | M2, D1 | TC |
M3 | M3, D1 | TA |
M3 | M3, D2 | TA |
M3 | M3, D3 | TB |
M3 | M3, D4 | TA |
M3 | M3, D5 | TB |
M3 | M3, D6 | TC |
M3 | M3, D7 | TC |
--
I need something like this:
master_name | TA | TB | TC |
M1 | M1, D1 |||
M1 || M1, D2 ||
M1 | M1, D3 |||
M1 ||| M1, D4 |
M2 ||| M2, D1 |
M3 | M3, D1 |||
M3 | M3, D2 |||
M3 || M3, D3 | |
M3 | M3, D4 |||
M3 || M3, D5 ||
M3 ||| M3, D6 |
M3 ||| M3, D7 |
Does anyone know how to do that in Postgresql? I run version 7.3.4.
Thanks for any idea you might have.
Philippe Lang
---(end of broadcast)---
TIP 7: don't forget to increase your free space map settings
Re: [SQL] crosstabs
Here is a solution:
-- QUERY
SELECT
master_name,
CASE WHEN type = 'TA' THEN detail_name END as TA,
CASE WHEN type = 'TB' THEN detail_name END as TB,
CASE WHEN type = 'TC' THEN detail_name END as TC
FROM
master INNER JOIN detail
ON master.id = detail.id_master
INNER JOIN type
ON detail.code_type = type.code
ORDER by master.id, detail.id;
I'm not sure if we could do that without CASE... END...
-Message d'origine-
De : [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] De la part de Philippe Lang
Envoyé : jeudi, 19. février 2004 17:02
À : [EMAIL PROTECTED]
Objet : [SQL] crosstabs
Hello,
I need to do something similar to a cross tabulation, but without any aggregation.
Here is an example:
-- TABLE DEFINITION
CREATE TABLE public.type
(
code char(1) PRIMARY KEY,
type varchar(30)
) WITHOUT OIDS;
CREATE TABLE public.master
(
id int4 PRIMARY KEY,
master_name varchar(30)
) WITHOUT OIDS;
CREATE TABLE public.detail
(
id int4 PRIMARY KEY,
code_type char(1) REFERENCES public.type,
id_master int4 REFERENCES public.master,
detail_name varchar(30)
) WITHOUT OIDS;
-- DATA
INSERT INTO public.type VALUES('A', 'TA');
INSERT INTO public.type VALUES('B', 'TB');
INSERT INTO public.type VALUES('C', 'TC');
INSERT INTO public.master VALUES(1, 'M1');
INSERT INTO public.master VALUES(2, 'M2');
INSERT INTO public.master VALUES(3, 'M3');
INSERT INTO public.detail VALUES(1, 'A', 1, 'M1, D1');
INSERT INTO public.detail VALUES(2, 'B', 1, 'M1, D2');
INSERT INTO public.detail VALUES(3, 'A', 1, 'M1, D3');
INSERT INTO public.detail VALUES(4, 'C', 1, 'M1, D4');
INSERT INTO public.detail VALUES(5, 'C', 2, 'M2, D1');
INSERT INTO public.detail VALUES(6, 'A', 3, 'M3, D1');
INSERT INTO public.detail VALUES(7, 'A', 3, 'M3, D2');
INSERT INTO public.detail VALUES(8, 'B', 3, 'M3, D3');
INSERT INTO public.detail VALUES(9, 'A', 3, 'M3, D4');
INSERT INTO public.detail VALUES(10, 'B', 3, 'M3, D5');
INSERT INTO public.detail VALUES(11, 'C', 3, 'M3, D6');
INSERT INTO public.detail VALUES(12, 'C', 3, 'M3, D7');
-- QUERY
SELECT
master_name,
detail_name,
type
FROM
master INNER JOIN detail
ON master.id = detail.id_master
INNER JOIN type
ON detail.code_type = type.code
ORDER by master.id, detail.id;
The result of that is:
--
master_name | detail_name | type |
--
M1 | M1, D1 | TA |
M1 | M1, D2 | TB |
M1 | M1, D3 | TA |
M1 | M1, D4 | TC |
M2 | M2, D1 | TC |
M3 | M3, D1 | TA |
M3 | M3, D2 | TA |
M3 | M3, D3 | TB |
M3 | M3, D4 | TA |
M3 | M3, D5 | TB |
M3 | M3, D6 | TC |
M3 | M3, D7 | TC |
--
I need something like this:
master_name | TA | TB | TC |
M1 | M1, D1 |||
M1 || M1, D2 ||
M1 | M1, D3 |||
M1 ||| M1, D4 |
M2 ||| M2, D1 |
M3 | M3, D1 |||
M3 | M3, D2 | | |
M3 || M3, D3 ||
M3 | M3, D4 |||
M3 || M3, D5 ||
M3 ||| M3, D6 |
M3 ||| M3, D7 |
Does anyone know how to do that in Postgresql? I run version 7.3.4.
Thanks for any idea you might have.
Philippe Lang
---(end of broadcast)---
TIP 7: don't forget to increase your free space map settings
---(end of broadcast)---
TIP 5: Have you checked our extensive FAQ?
http://www.postgresql.org/docs/faqs/FAQ.html
[SQL] sub-select parameter problem
Hello, Imagine the following query: --- SELECT tableA.field1, tableA.field2, tableB.field1, tableB.field2, ( SELECT tableC.field2 FROM tableC WHERE tableC.field1 = tableB.field1 - 1; ) AS p FROM tableA INNER JOIN tableB ON tableA.pk = tableB.FK; --- It works fine. Now, I need to do something else: the parameter of my sub-select is also a member of the table I'm selecting. --- SELECT tableA.field1, tableA.field2, tableB.field1, tableB.field2, ( SELECT tableB.field2 FROM tableB WHERE tableB.field1 = tableB.field1 (--> from-main-select?) - 1; ) AS p FROM tableA INNER JOIN tableB ON tableA.pk = tableB.FK; --- How can I refer to the tableB.field1 parameter from the main query? I've tried to do something like this, but without success: --- SELECT tableA.field1, tableA.field2, tableB.field1 AS param, tableB.field2, ( SELECT tableB.field2 FROM tableB WHERE tableB.field1 = param - 1;(--> does not work...) ) AS p FROM tableA INNER JOIN tableB ON tableA.pk = tableB.FK; --- The only workaround I found is to use CASE... WHEN, but this is not really robust, nor elegant. --- SELECT tableA.field1, tableA.field2, tableB.field1, tableB.field2, CASE WHEN tableB.field1 = 1 THEN ( SELECT tableB.field2 FROM tableB WHERE tableB.field1 = 0; ) WHEN tableB.field1 = 2 THEN ( SELECT tableB.field2 FROM tableB WHERE tableB.field1 = 1; ) WHEN tableB.field1 = 3 THEN ( SELECT tableB.field2 FROM tableB WHERE tableB.field1 = 2; ) ... etc... ELSE 0 END AS p, FROM tableA INNER JOIN tableB ON tableA.pk = tableB.FK; --- In my particular application, this is almost acceptable, but I'm sure there is a better way to do that... Thanks for your help! (And for reading, by the way!) ------- Philippe Lang Attik System ---(end of broadcast)--- TIP 9: the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
[SQL] function expression in FROM may not refer to other relations of same query level
Hello, I'm trying to use the ROWTYPE return value of a plpgsql function in a SELECT query. The test code is below. The following query is accepted: select id, usr, code, line1, line2 from tbl, get_lines(1); idusr code line1 line2 -- 1 one 1 A B 2 two 2 A B 3 three1 A B But the same query with a parameter returns an error: select id, usr, code, line1, line2 from tbl, get_lines(code); --> ERROR: function expression in FROM may not refer to other relations of same query level Is there another way to run this query and get: idusr code line1 line2 -- 1 one 1 A B 2 two 2 Z Z 3 three1 A B Thanks TEST CODE CREATE TYPE public.lines AS ( line1 varchar(10), line2 varchar(10) ); CREATE TABLE public.tbl ( id int4 PRIMARY KEY, usr varchar(10), code int4 ) WITHOUT OIDS; CREATE FUNCTION public.get_lines(int4) RETURNS lines AS ' DECLARE code ALIAS FOR $1; lines lines%rowtype; BEGIN IF code = 1 THEN lines.line1 = ''A''; lines.line2 = ''B''; ELSE lines.line1 = ''Z''; lines.line2 = ''Z''; END IF; RETURN lines; END; ' LANGUAGE 'plpgsql' VOLATILE; INSERT INTO tbl VALUES (1, 'one', 1); INSERT INTO tbl VALUES (2, 'two', 2); INSERT INTO tbl VALUES (3, 'three', 1); ---(end of broadcast)--- TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]
Re: [SQL] function expression in FROM may not refer to other relations of same query level
Hello, > Whats wrong with just using CASE: > > select id, usr, code, > case when code = 1 then 'A' else 'Z' end as line1, > case when code = 1 then 'A' else 'Z' end as line2 from tbl; The code I showed in my last mail was actually test code only. The logic is more complicated, and I'm not sure it's possible to implement it with a SELECT... CASE. What's more, the "get_lines" function already exists, and is already used in different parts of the database. I would like, if possible, to use it without changing it, or duplicating code. Philippe ---(end of broadcast)--- TIP 6: Have you searched our list archives? http://archives.postgresql.org
Re: [SQL] function expression in FROM may not refer to other relations of same query level
I found one solution: select id, usr, code, (get_lines(code)).line1, (get_lines(code)).line2 from tbl; The problem now is that get_lines is being called twice per line. (I check with a RAISE NOTICE). Philippe -Message d'origine- De : [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] De la part de Philippe Lang Envoyé : mercredi, 11. août 2004 08:41 À : [EMAIL PROTECTED] Objet : Re: [SQL] function expression in FROM may not refer to other relations of same query level Hello, > Whats wrong with just using CASE: > > select id, usr, code, > case when code = 1 then 'A' else 'Z' end as line1, > case when code = 1 then 'A' else 'Z' end as line2 from tbl; The code I showed in my last mail was actually test code only. The logic is more complicated, and I'm not sure it's possible to implement it with a SELECT... CASE. What's more, the "get_lines" function already exists, and is already used in different parts of the database. I would like, if possible, to use it without changing it, or duplicating code. Philippe ---(end of broadcast)--- TIP 6: Have you searched our list archives? http://archives.postgresql.org ---(end of broadcast)--- TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]
Re: [SQL] function expression in FROM may not refer to other relations of same query level
> > The problem now is that get_lines is being called twice per line. > > Is get_lines() defined as IMMUTABLE? Should it be? I have tried defining get_lines as "IMMUTABLE", or "WITH (iscachable)", but it keeps on getting called twice per line in the following query... select id, usr, code, (get_lines(code)).line1, (get_lines(code)).line2 from tbl; I wish there was a way to run the query like this: select id, usr, code, CAST(get_lines(code) as lines) from tbl; ---(end of broadcast)--- TIP 7: don't forget to increase your free space map settings
Re: [SQL] function expression in FROM may not refer to other relations of same query level
Thanks a lot for your support. With a subselect and offset 0, the function is called only once per row, that's fine. Here is the final test code, in case it can help anyone. --- CREATE TYPE public.lines AS ( line1 varchar(10), line2 varchar(10) ); CREATE TABLE public.tbl ( id int4 PRIMARY KEY, usr varchar(10), code int4 ) WITHOUT OIDS; CREATE FUNCTION public.get_lines(int4) RETURNS lines AS ' DECLARE code ALIAS FOR $1; lines lines%rowtype; BEGIN IF code = 1 THEN lines.line1 = ''A''; lines.line2 = ''B''; ELSE lines.line1 = ''Z''; lines.line2 = ''Z''; END IF; RAISE NOTICE ''---> get_lines was called...''; RETURN lines; END; ' LANGUAGE 'plpgsql' VOLATILE; INSERT INTO tbl VALUES (1, 'one', 1); INSERT INTO tbl VALUES (2, 'two', 2); INSERT INTO tbl VALUES (3, 'three', 1); INSERT INTO tbl VALUES (4, 'four', 2); select id, usr, code, (get_lines_data).line1, (get_lines_data).line2 from ( select id, usr, code, get_lines(code) as get_lines_data from tbl offset 0 ) as ss; --- Philippe Lang -Message d'origine- De : Tom Lane [mailto:[EMAIL PROTECTED] Envoyé : jeudi, 12. août 2004 16:31 À : Philippe Lang Cc : [EMAIL PROTECTED] Objet : Re: [SQL] function expression in FROM may not refer to other relations of same query level "Philippe Lang" <[EMAIL PROTECTED]> writes: > I wish there was a way to run the query like this: > select > id, > usr, > code, > CAST(get_lines(code) as lines) > from tbl; You can do something like this: regression=# create type complex as (r float8, i float8); CREATE TYPE regression=# create function fooey(float8) returns complex as regression-# 'select $1 + 1, $1 + 2' language sql; CREATE FUNCTION regression=# select f1, (fooey).r, (fooey).i from regression-# (select f1, fooey(f1) as fooey from float8_tbl) ss; f1 | r | i ---+---+--- 0 | 1 | 2 -34.84 |-33.84 |-32.84 -1004.3 | -1003.3 | -1002.3 -1.2345678901234e+200 | -1.2345678901234e+200 | -1.2345678901234e+200 -1.2345678901234e-200 | 1 | 2 (5 rows) Note the odd-looking parenthesization --- you can't write just "fooey.r" because that looks like it should be a table and field name, not a field name that is selected from. If the sub-select is too simple, as it is in this case, the planner is likely to "flatten out" the query into select f1, (fooey(f1)).r, (fooey(f1)).i from float8_tbl; thus defeating your purpose of not calling the function twice. The currently best hack for preventing this is to add "OFFSET 0" to the sub-select: select f1, (fooey).r, (fooey).i from (select f1, fooey(f1) as fooey from float8_tbl offset 0) ss; regards, tom lane ---(end of broadcast)--- TIP 8: explain analyze is your friend
[SQL] Disable trigger with Postgresql 7.4.x?
Hello, I read in an old thread http://archives.postgresql.org/pgsql-hackers/2002-08/msg00079.php ... that starting with Postgresql 7.3, there is a new way to disable and enable triggers in Postgresql. The "old" way was: update pg_class set reltriggers=0 where relname = 'YOUR_TABLE_NAME'; update pg_class set reltriggers = count(*) from pg_trigger where pg_class.oid=tgrelid and relname='YOUR_TABLE_NAME'; What is the recommended way of doing that under Postgresql 7.4.x? Thanks Philippe Lang ---(end of broadcast)--- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html
Re: [SQL] stored procedures and type of returned result.
Patrice, You might have a look at "views" as well. That's not strictily speaking a stored procedure, but maybe it's what you are searching for? Philippe Lang -Message d'origine- De : [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] De la part de Richard Huxton Envoyé : mardi, 24. août 2004 11:26 À : Patrice OLIVER Cc : [EMAIL PROTECTED] Objet : Re: [SQL] stored procedures and type of returned result. Patrice OLIVER wrote: > Hello, > > I'm new in PostgreSQL. It's very cool. Hello, and yes it is isn't it :-) > I would like to know how to return a set of records from a stored > procedure. > > For example, i would like to execute these sql command from a stored > procedure : > > select t.typnum, t.typcom, t.typcateg, s.symurlgraph from structure.type t > left join structure.symbole s > on t.typcode = s.typcode; Broadly speaking you'll want something like: CREATE TYPE my_return_type AS ( a integer, b text ); CREATE FUNCTION my_function(integer) RETURNS SETOF my_return_type AS ' SELECT foo_a, foo_b FROM foo WHERE foo_c = $1; ' LANGUAGE SQL; You don't need to define your own type if you want to return the same columns as a table, you can use the table-name instead. For more complex cases where you need procedural code, you probably want to read Stephan Szabo's set-returning-functions article on techdocs. http://techdocs.postgresql.org/guides/SetReturningFunctions HTH -- Richard Huxton Archonet Ltd ---(end of broadcast)--- TIP 3: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly ---(end of broadcast)--- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html
[SQL] Datetime conversion in WHERE clause
Hello, I'm converting a varchar to a date in a search routine which looks like: -- CREATE FUNCTION public.search_data(varchar) RETURNS SETOF foo1 AS ' SELECT DISTINCT foo1.* FROM foo1 LEFT JOIN foo2 ON foo2.fk = foo1.pk WHERE lower(foo1.text_data1) LIKE lower($1) OR lower(foo1.text_data2) LIKE lower($1) OR foo1.date_data = $1::text:date OR lower(foo2.text_data3) LIKE lower($1) OR lower(foo2.text_data4) LIKE lower($1) ' LANGUAGE 'sql' VOLATILE; -- The problem with the ::text::date conversion is that the whole function fails if the search string parameter cannot be converted into a valid date, like 'test%', for example, which is valid for the other text fields. Is there a way to force the date conversion to fail sliently, and simply return a null in case the parameter is not a valid date? Thanks Philippe Lang ---(end of broadcast)--- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html
[SQL] Plperlu function & backticks return value -> truncated?
Hello,
I'm using the following show_users() function in order to retreive in
postgresql the output from the unix "ps" command.
When run directly from a shell, this code:
$ps = `ps -afux | grep postgres`;
@fields = split /\n/, $ps;
return "{" . join(",", @fields) . "}";
... runs fine.
But when run inside a plperlu function, lines are being truncated after
a certain width.
Is that a known limitation of plperlu? Or maybe something else?
Philippe
-- TYPE: line_type
CREATE TYPE public.line_type AS
(
line text
);
-- UTILITY FUNCTION: ps
CREATE FUNCTION public.ps()
RETURNS text[] AS
'
$ps = `ps -afux | grep postgres`;
@fields = split /\n/, $ps;
return "{" . join(",", @fields) . "}";
'
LANGUAGE 'plperlu' VOLATILE;
-- UTILITY FUNCTION: show_users
CREATE FUNCTION public.show_users()
RETURNS SETOF user_type AS
'
DECLARE
userstext[];
user_rec line_type%ROWTYPE;
iint2;
BEGIN
users = ps();
FOR i IN 1 .. array_upper(users, 1) LOOP
user_rec.line = users[i];
RETURN NEXT user_rec;
END LOOP;
RETURN;
END
'
LANGUAGE 'plpgsql' VOLATILE;
-- MAIN
select * from show_users();
---(end of broadcast)---
TIP 8: explain analyze is your friend
Re: [SQL] Plperlu function & backticks return value -> truncated?
Hello, Yes, I made a typo, sorry. I've been playing with different types this afternoon, that's why. But "user_type" was also made up of a "text" field, just like "line_type", so the problem is still here... -Message d'origine- De : Richard Huxton [mailto:[EMAIL PROTECTED] Envoyé : mercredi, 13. octobre 2004 17:25 À : Philippe Lang Cc : [EMAIL PROTECTED] Objet : Re: [SQL] Plperlu function & backticks return value -> truncated? > Is that a known limitation of plperlu? Or maybe something else? Depends if user_type is just a typo... ---(end of broadcast)--- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html
Re: [SQL] Plperlu function & backticks return value -> truncated?
Thanks! That's perfect... `ps -awfux | grep postgres` runs fine...
-Message d'origine-
De : Michael Fuhr [mailto:[EMAIL PROTECTED]
Envoyé : mercredi, 13. octobre 2004 17:47
À : Philippe Lang
Cc : [EMAIL PROTECTED]
Objet : Re: [SQL] Plperlu function & backticks return value -> truncated?
On Wed, Oct 13, 2004 at 05:07:05PM +0200, Philippe Lang wrote:
> When run directly from a shell, this code:
>
> $ps = `ps -afux | grep postgres`;
> @fields = split /\n/, $ps;
> return "{" . join(",", @fields) . "}";
>
> ... runs fine.
>
> But when run inside a plperlu function, lines are being truncated
> after a certain width.
Many versions of ps truncate lines at a certain length if they can't determine the
terminal size. Since you're running ps from inside the backend, there's probably no
terminal to check. Check the ps manual page to see if it supports an option like -w
(or multiple occurrences of -w) to increase the line length.
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/
---(end of broadcast)---
TIP 4: Don't 'kill -9' the postmaster
[SQL] Reuse previously calculated column in sql query?
Hello, Is it possible to reuse a previously calculated column in a following column, like: SELECT foo.val1 AS col1, long_calculation(foo.val1) AS col2, COL2 * 0.75 AS col3 FROM foo; instead of writing: SELECT foo.val1 AS col1, long_calculation(foo.val1) AS col2, long_calculation(foo.val1) * 0.75 AS col3 FROM foo; Philippe ---(end of broadcast)--- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])
[SQL] Postgresql inheritance workaround
Hi, Because of the actual limitations of Postgresql inheritance mecanism regarding constraints, I'm not willing to use it in my project, although it's exactly the kind of idea I need: In an order and manufacturing management system, several different items can be ordered, each of them with specific input parameters. Every item has its own table of "specific parameters", now, what is the best use of PK/FK in order to maintain integrity between the order lines and the items specific parameters tables? Has anyone already done that before? Thanks for your help, and for Posgresql by the way, which is really great... ------ Philippe Lang Attik System ---(end of broadcast)--- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])
[SQL] DROP TYPE without error?
Hi, Since it is not possible to use CREATE OR REPLACE TYPE, is there a way of using DROP TYPE on a non-existing type, without causing the entire script to abort? It may sound crazy to ask for this, but it could be really useful in my case, where Pl/Pgsql and Pl/Perl code is being generated automatically, based on data found in a database. Thanks - Philippe Lang ---(end of broadcast)--- TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]
Re: [SQL] outer join in ms query
Or add a view to your PG database, and simply issue a select from Excel... That faster and easier to maintain that any code you can write client-side... -Message d'origine- De : [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] De la part de Jeff Eckermann Envoyé : lundi, 18. avril 2005 16:51 À : [email protected] Objet : Re: [SQL] outer join in ms query MS Query is crippled. If you want to do much from Excel, you will need to write code. But it's not difficult. ADO is a good choice for this. "gad renert via DBMonster.com" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > Hello, I am a novice with SQL, I have 2 tables > (transfer) > bar_code | quant | date > 723445...| 2 |01/03/2005 > > (imports) > > bar_code | serial_no | supplier > > > I want to add to the first table (transfer) next to each barcode the > suppliers name from the (imports) table. > > ms query doesn't allow me to do outer joins. > > I tried: > SELECT transfer.bar_code, transfer.quant, imports.supplier FROM > transfer left join imports on transfer.bar_code=imports.bar_cod GROUP > BY transfer.bar_code > > and it didn't work popperly, the (transfer) table is modified. > what i want to do is very similar to the VLOOKUP function in EXCELL > > Hope that someone can help me. > > Gadi > > -- > Message posted via http://www.dbmonster.com ---(end of broadcast)--- TIP 9: the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match ---(end of broadcast)--- TIP 9: the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
[SQL] Concatenate strings using GROUP BY
Hi, Let's say we have a query like: SELECT id, fk, str FROM foo ... which returns: idfkstr --- 1 1 a 2 1 b 3 2 c Is there a pure SQL way of contactenating str values into a single string, and get instead: idfkstr --- 1 1 a/b 2 12c I was thinking of something like: SELECT id, fk, CONCAT(str || '/') FROM FOO GROUP BY fk Do we have to use PL/PGSQL for that? Thanks, -- Philippe Lang, Ing. Dipl. EPFL Attik System rte de la Fonderie 2 1700 Fribourg Switzerland http://www.attiksystem.ch Tel: +41 (26) 422 13 75 Fax: +41 (26) 422 13 76 Email:[EMAIL PROTECTED] smime.p7s Description: S/MIME cryptographic signature
[SQL] pgxml & xpath_table
Hi,
I'm playing with the contrib/pgxml library under PG 8.1.4, and I'm not sure if
what I found with pgxml is a feature of a bug:
I've got the following table:
CREATE TABLE test
(
id int4 NOT NULL,
xml varchar(200),
CONSTRAINT pk PRIMARY KEY (id)
)
WITHOUT OIDS;
INSERT INTO test VALUES (1, '123112233');
INSERT INTO test VALUES (2, '111222333111222333');
If I launch this query:
select * from
xpath_table('id','xml','test',
'/doc/@num|/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c','1=1') AS t(id
int4, doc_num varchar(10), line_num varchar(10), val1 int4, val2 int4, val3
int4)
where id = 1
order by doc_num, line_num
I get:
iddoc_num line_numval1val2val3
1 C1 L1 1 2 3
1 L2 11 22 33
I was expecting doc_num would receive twice the C1 value, just like with a
normal sql join.
Regards,
--
Philippe Lang, Ing. Dipl. EPFL
Attik System
rte de la Fonderie 2
1700 Fribourg
Switzerland
http://www.attiksystem.ch
Tel: +41 (26) 422 13 75
Fax: +41 (26) 422 13 76
smime.p7s
Description: S/MIME cryptographic signature
[SQL] WITH RECURSION output ordering with trees
Hi, I'm playing with the new "WITH RECURSIVE" feature of 8.4. I'm trying to figure out how to use it with trees. Here is the test code I use: - --DROP TABLE recursion; CREATE TABLE recursion ( id serial, lookup varchar(16), parent_id integer, primary key(id), foreign key(parent_id) references recursion(id) ); INSERT INTO recursion VALUES(1,'a1', NULL); INSERT INTO recursion VALUES(2,'b11',1); INSERT INTO recursion VALUES(645, 'c111', 2); INSERT INTO recursion VALUES(823, 'c112', 2); INSERT INTO recursion VALUES(243, 'c113', 2); INSERT INTO recursion VALUES(6,'b12',1); INSERT INTO recursion VALUES(845, 'c121', 6); INSERT INTO recursion VALUES(583, 'c122', 6); INSERT INTO recursion VALUES(9,'b13',1); INSERT INTO recursion VALUES(10, 'c131', 9); WITH RECURSIVE parse_tree (depth, id, lookup, parent_id) AS ( SELECT 0, parent.id, parent.lookup, parent.parent_id FROM recursion AS parent WHERE parent_id IS NULL UNION ALL SELECT parent.depth + 1, child.id, child.lookup, child.parent_id FROM parse_tree parent, recursion AS child WHERE child.parent_id = parent.id ) SELECT * FROM parse_tree; - Here is the result: depth | id | lookup | parent_id ---+-++--- 0 | 1 | a1 | 1 | 2 | b11| 1 1 | 6 | b12| 1 1 | 9 | b13| 1 2 | 645 | c111 | 2 2 | 823 | c112 | 2 2 | 243 | c113 | 2 2 | 845 | c121 | 6 2 | 583 | c122 | 6 2 | 10 | c131 | 9 I'd like to perform a real recursion, and show the tree structure in a more appopriate way, like this: depth | id | lookup | parent_id ---+-++--- 0 | 1 | a1 | 1 | 2 | b11| 1 2 | 645 | c111 | 2 2 | 823 | c112 | 2 2 | 243 | c113 | 2 1 | 6 | b12| 1 2 | 845 | c121 | 6 2 | 583 | c122 | 6 1 | 9 | b13| 1 2 | 10 | c131 | 9 Any idea how to do that? (without trying to sort on the lookup column, whose values can be random outside this test) Best regards, Philippe Lang -- Sent via pgsql-sql mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql
Re: [SQL] WITH RECURSION output ordering with trees
[email protected] wrote: > Hi, > > I'm playing with the new "WITH RECURSIVE" feature of 8.4. I'm trying > to figure out how to use it with trees. > > Here is the test code I use: > > - > --DROP TABLE recursion; > > CREATE TABLE recursion > ( > id serial, > lookup varchar(16), > parent_id integer, > primary key(id), > foreign key(parent_id) references recursion(id) ); > > INSERT INTO recursion VALUES(1,'a1', NULL); > INSERT INTO recursion VALUES(2,'b11',1); > INSERT INTO recursion VALUES(645, 'c111', 2); > INSERT INTO recursion VALUES(823, 'c112', 2); > INSERT INTO recursion VALUES(243, 'c113', 2); > INSERT INTO recursion VALUES(6,'b12',1); > INSERT INTO recursion VALUES(845, 'c121', 6); > INSERT INTO recursion VALUES(583, 'c122', 6); > INSERT INTO recursion VALUES(9,'b13',1); > INSERT INTO recursion VALUES(10, 'c131', 9); > > WITH RECURSIVE parse_tree (depth, id, lookup, parent_id) AS ( > SELECT > 0, > parent.id, > parent.lookup, > parent.parent_id > FROM recursion AS parent > WHERE parent_id IS NULL > > UNION ALL > > SELECT > parent.depth + 1, > child.id, > child.lookup, > child.parent_id > FROM parse_tree parent, recursion AS child > WHERE child.parent_id = parent.id > ) > > SELECT * FROM parse_tree; > - > > Here is the result: > > depth | id | lookup | parent_id > ---+-++--- > 0 | 1 | a1 | > 1 | 2 | b11| 1 > 1 | 6 | b12| 1 > 1 | 9 | b13| 1 > 2 | 645 | c111 | 2 > 2 | 823 | c112 | 2 > 2 | 243 | c113 | 2 > 2 | 845 | c121 | 6 > 2 | 583 | c122 | 6 > 2 | 10 | c131 | 9 > > I'd like to perform a real recursion, and show the tree structure in > a more appopriate way, like this: > > depth | id | lookup | parent_id > ---+-++--- > 0 | 1 | a1 | > 1 | 2 | b11| 1 > 2 | 645 | c111 | 2 > 2 | 823 | c112 | 2 > 2 | 243 | c113 | 2 > 1 | 6 | b12| 1 > 2 | 845 | c121 | 6 > 2 | 583 | c122 | 6 > 1 | 9 | b13| 1 > 2 | 10 | c131 | 9 > > Any idea how to do that? (without trying to sort on the lookup > column, whose values can be random outside this test) Hi again, I reply to my own post: I found a way to parse the tree with the help of the tablefunc contrib package: - SELECT t.depth, t.id, r.lookup, t.parent_id FROM connectby('recursion', 'id', 'parent_id', 'lookup', '1', 0) AS t(id integer, parent_id integer, depth integer, o integer) INNER JOIN recursion AS r ON t.id = r.id - depth | id | lookup | parent_id ---+-++--- 0 | 1 | a1 | 1 | 2 | b11| 1 2 | 645 | c111 | 2 2 | 823 | c112 | 2 2 | 243 | c113 | 2 1 | 6 | b12| 1 2 | 845 | c121 | 6 2 | 583 | c122 | 6 1 | 9 | b13| 1 2 | 10 | c131 | 9 I guess this is hard to achieve with a "WITH RECURSIVE" call. So my question is now: is the inclusion of "START WITH... CONNECT BY" planned for Postgresql? I read a patch had been developed for Postgresql 8.3: http://www.postgresql-support.de/blog/blog_hans.html Best regards, Philippe Lang -- Sent via pgsql-sql mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql
Re: [SQL] WITH RECURSION output ordering with trees
[email protected] wrote: > Philippe Lang, 10.07.2009 11:10: >> Hi, >> >> I'm playing with the new "WITH RECURSIVE" feature of 8.4. I'm trying >> to figure out how to use it with trees. >> >> Here is the test code I use: >> >> I'd like to perform a real recursion, and show the tree structure in >> a more appopriate way, like this: >> >> Any idea how to do that? (without trying to sort on the lookup >> column, whose values can be random outside this test) > > > The manual has a nice hint on this adding up IDs to "generate" a path > like column that can be used for sorting. > > Try the following: > > WITH RECURSIVE parse_tree (depth, id, lookup, parent_id, sort_path) > AS ( SELECT 0, > parent.id, > cast(parent.lookup as text), > parent.parent_id, > array[0] as sort_path > FROM recursion_sample parent > WHERE parent_id IS NULL > UNION ALL > SELECT > parent.depth + 1, > child.id, > rpad(' ', depth * 2) || child.lookup, > child.parent_id, > parent.sort_path || child.id > FROM parse_tree parent JOIN recursion_sample child on > child.parent_id = parent.id ) > select id, lookup > from parse_tree > order by sort_path > ; > > This will output: > > id | lookup > -+ >1 | a1 >2 | b11 > 243 | c113 > 645 | c111 > 823 | c112 >6 | b12 > 583 | c122 > 845 | c121 >9 | b13 > 10 | c131 > (10 rows) Hi Thomas, Thanks for your answer. Si there a built-in function that would allow generating the sort path based on the value of the lookup column, instead of the id, which has no meaning at all? If yes, we would get instead: depth | id | lookup | parent_id ---+-++--- 0 | 1 | a1 | 1 | 2 | b11| 1 2 | 645 | c111 | 2 2 | 823 | c112 | 2 2 | 243 | c113 | 2 1 | 6 | b12| 1 2 | 845 | c121 | 6 2 | 583 | c122 | 6 1 | 9 | b13| 1 2 | 10 | c131 | 9 Best regards, Philippe Lang -- Sent via pgsql-sql mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql
Re: [SQL] WITH RECURSION output ordering with trees
[email protected] wrote: > In article > , > "Philippe Lang" writes: > >> Thanks for your answer. Si there a built-in function that would allow >> generating the sort path based on the value of the lookup column, >> instead of the id, which has no meaning at all? > >> If yes, we would get instead: > >> depth | id | lookup | parent_id >> ---+-++--- >> 0 | 1 | a1 | >> 1 | 2 | b11| 1 >> 2 | 645 | c111 | 2 >> 2 | 823 | c112 | 2 >> 2 | 243 | c113 | 2 >> 1 | 6 | b12| 1 >> 2 | 845 | c121 | 6 >> 2 | 583 | c122 | 6 >> 1 | 9 | b13| 1 >> 2 | 10 | c131 | 9 > > Try this: > > WITH RECURSIVE parse_tree (depth, id, lookup, parent_id, path) AS ( > SELECT 0, parent.id, parent.lookup, parent.parent_id, > parent.lookup::text FROM recursion AS parent > WHERE parent_id IS NULL > UNION ALL > SELECT parent.depth + 1, child.id, child.lookup, child.parent_id, > parent.path || '.' || child.lookup > FROM parse_tree parent > JOIN recursion AS child ON child.parent_id = parent.id > ) > SELECT depth, id, lookup, parent_id > FROM parse_tree > ORDER BY path Works great, thanks! Of course, concatenating lookups... Best regards, Philippe -- Sent via pgsql-sql mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql
Re: [SQL] Way to reverse ordering of an IP ... ?
[EMAIL PROTECTED] wrote: > for Reverse DNS purposes, I'd like to reverse an IP ... > > ie: 200.46.204.1 would become 1.204.46.200 > > Is there an easy way of doing this *short* of writing a > plpgsql function? > > I've checked the docs, and found the substring() function > that allows for using a regex, which I thought might allow > this, but can't seem to figure out a proper format for it ;( > > If I have to write a function to do it, fine ... just wanted > to make sure I wasn't missing something first ... Hi, You can use (\d+)\.(\d+)\.(\d+)\.(\d+) for the match, and \4.\3.\2.\1 for the replacement in your Regexp. Cheers, -- Philippe Lang, Ing. Dipl. EPFL Attik System rte de la Fonderie 2 1700 Fribourg Switzerland http://www.attiksystem.ch Tel: +41 (26) 422 13 75 Fax: +41 (26) 422 13 76 smime.p7s Description: S/MIME cryptographic signature
[SQL] Table transform query
Hi, I'm trying to find out how to transform this kind of table data (history of rental data in a firm): date serial delivery -- 1 1 L 1 2 L 1 3 L 2 1 R 2 2 R 2 4 L 3 5 L 3 3 R 3 4 R 4 1 L ... into this: serial dateL dateR 1 1 2 1 4 2 1 2 3 1 3 4 2 3 5 3 Basically, data on table 1 means: - on date 1, product with serial 1 is sent to the customer - on date 1, product with serial 2 is sent to the customer - on date 1, product with serial 3 is sent to the customer - on date 2, product with serial 1 comes back ... On table 2, data means: - Product with serial 1 is sent to the customer on date 1, and comes back on date 2 - Product with serial 1 is sent to the customer on date 4, and hasn't come back yet ... Do you think there is a generic SQL solution to this problem, like crosstab or pivot table? I'm thinking of doing things in a "procedural" plpgsql manner... Any idea is welcome. Thanks! Philippe ---(end of broadcast)--- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly
Re: [SQL] Table transform query
[EMAIL PROTECTED] wrote: > Hi, > > I'm trying to find out how to transform this kind of table data > (history of rental data in a firm): ... I have answred my own question: yes, there is a pure SQL solution, with a subselect: CREATE TABLE foo ( serial integer, delivery character(1), date integer ); INSERT INTO foo (serial, delivery, date) VALUES (1, 'L', 1); INSERT INTO foo (serial, delivery, date) VALUES (2, 'L', 1); INSERT INTO foo (serial, delivery, date) VALUES (3, 'L', 1); INSERT INTO foo (serial, delivery, date) VALUES (1, 'R', 2); INSERT INTO foo (serial, delivery, date) VALUES (2, 'R', 2); INSERT INTO foo (serial, delivery, date) VALUES (4, 'L', 2); INSERT INTO foo (serial, delivery, date) VALUES (5, 'L', 3); INSERT INTO foo (serial, delivery, date) VALUES (3, 'R', 3); INSERT INTO foo (serial, delivery, date) VALUES (4, 'R', 3); INSERT INTO foo (serial, delivery, date) VALUES (1, 'L', 4); - select f.serial, f.date as dateL, ( select f2.date from foo as f2 where f2.serial = f.serial and f2.date > f.date and f2.delivery = 'R' order by f2.date asc limit 1 ) as dateR from foo as f where f.delivery = 'L' order by f.serial, f.date - I'm not sure if we could use a self-join here... Cheers, Philippe Lang ---(end of broadcast)--- TIP 2: Don't 'kill -9' the postmaster
Re: [SQL] Table transform query
> A take on a self-join: > > SELECT t1.serial, t1.date as dateL, MIN(t2.date) as dateR FROM t t1 > LEFT JOIN t t2 ON t1.serial = t2.serial AND t1.date < t2.date AND > t2.delivery = 'R' > WHERE t1.delivery = 'L' > GROUP BY t1.serial, t1.date > > Whether this is any clearer, or runs faster, than the correlated > subquery (which could be simplified by using MIN instead of LIMIT 1) > is up for debate and test, respectively. Hi Nis, Thanks for your tip with the "MIN" operator. I always imagined a self-join solution was faster than a query with a subselect. With a quick test, it seems to be the case here. CREATE TABLE foo ( serial integer, delivery character(1), date integer ); INSERT INTO foo (serial, delivery, date) VALUES (1, 'L', 1); INSERT INTO foo (serial, delivery, date) VALUES (2, 'L', 1); INSERT INTO foo (serial, delivery, date) VALUES (3, 'L', 1); INSERT INTO foo (serial, delivery, date) VALUES (1, 'R', 2); INSERT INTO foo (serial, delivery, date) VALUES (2, 'R', 2); INSERT INTO foo (serial, delivery, date) VALUES (4, 'L', 2); INSERT INTO foo (serial, delivery, date) VALUES (5, 'L', 3); INSERT INTO foo (serial, delivery, date) VALUES (3, 'R', 3); INSERT INTO foo (serial, delivery, date) VALUES (4, 'R', 3); INSERT INTO foo (serial, delivery, date) VALUES (1, 'L', 4); -- Subselect SELECT f.serial, f.date as dateL, ( SELECT MIN(f2.date) FROM foo AS f2 WHERE f2.serial = f.serial AND f2.date > f.date AND f2.delivery = 'R' ) AS dateR FROM foo AS f WHERE f.delivery = 'L' ORDER BY f.serial, f.date -- Self-join SELECT t1.serial, t1.date as dateL, MIN(t2.date) as dateR FROM foo t1 LEFT JOIN foo t2 ON t1.serial = t2.serial AND t1.date < t2.date AND t2.delivery = 'R' WHERE t1.delivery = 'L' GROUP BY t1.serial, t1.date ORDER BY t1.serial, t1.date ---(end of broadcast)--- TIP 6: explain analyze is your friend
[SQL] Temporal databases
Hi, Does anyone have experience, tips, links, regarding how to build temporal databases with Postgresql? Thanks Philippe ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
[SQL] quote_nullable alternative?
Hi, There has been a recent discussion on the hacker mailing-list recently, regarding a new patch for postgresql, that returns 'NULL' instead of NULL when a NULL value is passed as a parameter. It's exactly what I need on my 8.2.5 server. Is there an alternative to patching the server in order to get that kind of feature, for example with plpgsql code? Because of that bug: http://www.postgresql.org/docs/faqs.FAQ.html#item4.19 ... I'm obliged to call EXECUTE at every temporary table call, and constructing the query string where parameters can be NULL is really a nightmare... Thanks Philippe Lang ---(end of broadcast)--- TIP 6: explain analyze is your friend
Re: [SQL] quote_nullable alternative?
[EMAIL PROTECTED] wrote: > Hi, > > There has been a recent discussion on the hacker mailing-list > recently, regarding a new patch for postgresql, that returns 'NULL' > instead of NULL when a NULL value is passed as a parameter. > > It's exactly what I need on my 8.2.5 server. > > Is there an alternative to patching the server in order to get that > kind of feature, for example with plpgsql code? > > Because of that bug: > > http://www.postgresql.org/docs/faqs.FAQ.html#item4.19 > > ... I'm obliged to call EXECUTE at every temporary table call, and > constructing the query string where parameters can be NULL is really > a nightmare... > > Thanks Hi, It might not be the most elegant solution, but I ended up writing these functions to solve my problem: CREATE OR REPLACE FUNCTION nullable_param(param text) RETURNS text AS $$ BEGIN IF param IS NULL THEN RETURN 'NULL'; ELSE RETURN || param || ; END IF; END $$ LANGUAGE 'plpgsql' VOLATILE; CREATE OR REPLACE FUNCTION nullable_param(param varchar) RETURNS varchar AS $$ BEGIN IF param IS NULL THEN RETURN 'NULL'; ELSE RETURN || param || ; END IF; END $$ LANGUAGE 'plpgsql' VOLATILE; CREATE OR REPLACE FUNCTION nullable_param(param decimal) RETURNS varchar AS $$ BEGIN IF param IS NULL THEN RETURN 'NULL'; ELSE RETURN CAST(param AS varchar); END IF; END $$ LANGUAGE 'plpgsql' VOLATILE; CREATE OR REPLACE FUNCTION nullable_param(param int) RETURNS varchar AS $$ BEGIN IF param IS NULL THEN RETURN 'NULL'; ELSE RETURN CAST(param AS varchar); END IF; END $$ LANGUAGE 'plpgsql' VOLATILE; CREATE OR REPLACE FUNCTION nullable_param(param date) RETURNS varchar AS $$ BEGIN IF param IS NULL THEN RETURN 'NULL'; ELSE RETURN || param || ; END IF; END $$ LANGUAGE 'plpgsql' VOLATILE; Regards, Philippe ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [SQL] Temporal databases
[EMAIL PROTECTED] wrote: > Hi Philippe, > Have a look at the post I made to the pgsql-sql list I made on 6th > November 2007 (day before you posted this). It contains alot of stuff > for temporal tables within Postgres. > However temporal tables (when done properly) are a very complex > subject at the best of times. It depends how much you want to > integrate them. A good place to start is Joe Celko's book "SQL For > Smarties" and Richard Snodgrass' book "Developing Time-Oriented > Database Applications in SQL" - this book is no longer in print, but > is downloadable (for FREE!) from: > http://www.cs.arizona.edu/~rts/tdbbook.pdf > Richard Snodgrass is one of the leading experts in the field. I warn > you - the book is heavy going - but so worth it!! > > Keith Hi Keith, I saw your post a few minutes after I posted mine, but I wasn't aware of the free book of Richard Snodgrass. Thanks for the link! Have you ever heard about some sort of database extension, or plugin, that allows using databases "temporally" without have to explicitely add code in into the schema? Is there an SQL standard already defined for querying databases temporally? I think I read about a "Time Connector" or something similar for Oracle, a few years ago... Regards, Philippe Lang ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [SQL] Temporal databases
Keith Carr wrote: > On Monday 12 November 2007 09:07, you wrote: > > Hi Philippe, > I do not know of any "extension" or "plugin" that can be used to give > database engines "temporality". Temporality will always be a tricky > subject and it would be impossible to code something general that > would work for any single situation. For example, on some tables you > may only want Valid Time recorded, on some tables only Transaction > Time and in some cases both (or in other cases neither). How would it > know which one? Also, when it came to queries updatating, deleting or > even just selecting, which criteria would it now to do this by in > this situation? > > There is no SQL standard for querying temporal databases as far as I > am aware. > This would be considered to be "schema" and so i presume, outside the > remit of the SQL standards committee. The closest that the SQL > standards committee will get to this is defining the structure within > which dates and times will be held and operated on in a "logical" > sense. > > Sure this makes temporal databases hard work, but this is the whole > point of a SQL database and SQL programmers - data integrity for a > given situation! > Otherwise we may as well be letting the company's accountants go off > designing databases using Access and spreadsheets?! And we ALL > know we don't want that, because when it goes wrong (because there > was no data > integrity) you will be the one left to sort the mess out.. ;) > > Hope this has helped in some way. > Keith Hi Keith, Thanks for your answer. I haven't been playing with temporal databases at all, so pardon my lack of precision, but naively I was imaginating something that would more or less look like: --- CREATE TABLE foo ( id integer, s varchar(64) ) WITH TEMPORAL VALID TIME; SET CURRENT_TIME = '2007-06-01'::date; INSERT INTO foo(v, s) VALUES (1, 'first line'); INSERT INTO foo(v, s) VALUES (2, 'second line'); INSERT INTO foo(v, s) VALUES (3, 'third line'); SET CURRENT_TIME = '2007-06-02'::date; INSERT INTO foo(v, s) VALUES (4, 'fourth line'); DELETE FROM foo WHERE v = 1; --- Now "SET CURRENT_TIME = '2007-06-01'::date; SELECT * from foo;" would return: -- id s -- 1first line 2second line 3third line -- And "SET CURRENT_TIME = '2007-06-02'::date; SELECT * from foo;" would return: -- id s -- 2second line 3third line 4fourth line -- I guess it is much easier to imagine than to develop! For sure I've been watching "Back to future" too much when I was younger. Philippe Lang ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
[SQL] Concatenation through SQL
Hi, Here is small reduced test database: -- CREATE TABLE appointments ( id integer, name varchar(32), CONSTRAINT appointments_pkey PRIMARY KEY (id) ); CREATE TABLE employees ( id integer, appointment_id integer, name varchar(32), CONSTRAINT employees_pkey PRIMARY KEY (id), CONSTRAINT appointments_employees_fkey FOREIGN KEY (appointment_id) REFERENCES appointments (id) ); INSERT INTO appointments VALUES (1, 'app1'); INSERT INTO employees VALUES (1, 1, 'emp1'); INSERT INTO employees VALUES (2, 1, 'emp2'); INSERT INTO employees VALUES (3, 1, 'emp3'); INSERT INTO appointments VALUES (2, 'app2'); INSERT INTO employees VALUES (4, 2, 'emp1'); INSERT INTO employees VALUES (5, 2, 'emp4'); -- I'm trying to write an SQL query that would return this: --- appointmentcount_employeesemployees --- app1 3 emp1, emp2, emp3 app2 2 emp1, emp4, --- First part is easy to write: -- SELECT appointments.name AS appointment, (SELECT COUNT(*) FROM employees AS e where e.appointment_id = appointments.id) AS num_employees FROM appointments -- ... But concatenating employees name is harder, at least for me... I'm convinced this can be done with Set Returning Functions and a bit of plpgsql, but I was wondering if it would possible to write some kind of extension to Postgresql (operator?) that would allow this kind of syntax: -- SELECT appointments.name AS appointment, (SELECT COUNT(*) FROM employees AS e where e.appointment_id = appointments.id) AS num_employees (SELECT CONCAT(name, ', ') FROM employees AS e where e.appointment_id = appointments.id) AS employees FROM appointments -- ... where CONCAT suggest we want to concatenate the variable inside, with the separator ', ' inbetween. Thanks for your tips! Philippe Lang ---(end of broadcast)--- TIP 7: You can help support the PostgreSQL project by donating at http://www.postgresql.org/about/donate
Re: [SQL] Concatenation through SQL
[EMAIL PROTECTED] wrote:
> Philippe Lang <[EMAIL PROTECTED]> schrieb:
>
> 2 ways:
>
> * You can use something like this:
>
> test=*# select * from a;
> id | val
> +-
> 1 | foo
> 2 | bar
> (2 rows)
>
> test=*# select array_to_string(array(select val from a), ', ');
> array_to_string -
> foo, bar
> (1 row)
>
>
> * comma-aggregate, see
> http://www.zigo.dhs.org/postgresql/#comma_aggregate
Hi,
Thanks to all who responded, in particular Andreas. I'm always amazed by
the quality of both the Postgresql database and the support in its
newsgroups.
The "comma-aggregate" worked just fine for me. Here is the final
example, for those willing to test it. This will be more than useful!
---
CREATE TABLE appointments
(
id integer,
name varchar(32),
CONSTRAINT appointments_pkey PRIMARY KEY (id)
);
CREATE TABLE employees
(
id integer,
appointment_id integer,
name varchar(32),
CONSTRAINT employees_pkey PRIMARY KEY (id),
CONSTRAINT appointments_employees_fkey FOREIGN KEY (appointment_id)
REFERENCES appointments (id)
);
INSERT INTO appointments VALUES (1, 'app1');
INSERT INTO employees VALUES (1, 1, 'emp1');
INSERT INTO employees VALUES (2, 1, 'emp2');
INSERT INTO employees VALUES (3, 1, 'emp3');
INSERT INTO appointments VALUES (2, 'app2');
INSERT INTO employees VALUES (4, 2, 'emp1');
INSERT INTO employees VALUES (5, 2, 'emp4');
CREATE AGGREGATE array_accum (anyelement)
(
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);
SELECT
appointments.name AS appointment,
(SELECT COUNT(*) FROM employees AS e where e.appointment_id =
appointments.id) AS num_employees,
(SELECT array_to_string(array_accum(name),', ') FROM employees AS e
WHERE e.appointment_id = appointments.id) AS employees
FROM appointments
---
Result:
---
appointmentcount_employeesemployees
---
app1 3 emp1, emp2, emp3
app2 2 emp1, emp4,
---
Merry christmas to all.
Philippe
---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
choose an index scan if your joining column's datatypes do not
match
Re: [SQL] Concatenation through SQL
Pavel Stehule wrote: >> SELECT >> appointments.name AS appointment, >> (SELECT COUNT(*) FROM employees AS e where e.appointment_id = >> appointments.id) AS num_employees, >> (SELECT array_to_string(array_accum(name),', ') FROM employees AS e >> WHERE e.appointment_id = appointments.id) AS employees FROM >> appointments --- >> > > hello, > > one note: you can merge your two subselect into one. It's unimportant > on 100 rows, but it's can be important on thousands rows. > > nice a day > Pavel Hi Pavel, Since subselects must return one single column, is that what you are talking about? I have just modified the code you have posted before. --- SELECT name AS appointment, num_employees, employees FROM ( SELECT appointment_id, COUNT(*) AS num_employees, (SELECT array_to_string(array_accum(name),', ') FROM employees WHERE e.appointment_id = appointment_id) AS employees FROM employees e GROUP BY appointment_id )s JOIN appointments a on a.id = s.appointment_id; --- Philippe ---(end of broadcast)--- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq
[SQL] SQL tree duplication
Hi, I have the following kind of sql structure, in 3 levels: --- create table documents ( id serial, name varchar(50), primary key (id) ); create table lines ( id serial, name varchar(50), document_id integer, primary key (id), foreign key (document_id) references documents (id) ); create table line_details ( id serial, name varchar(50), line_id integer, primary key (id), foreign key (line_id) references lines (id) ); --- I'd like to be able to "duplicate" a document, with all of its lines and line details. Is there any easy way to do that with Postgresql? The only solution I can think of at the moment is to loop through all lines and line details, and replace foreign keys properly with values fetch with "currval". It should work just fine, but I was wondering if some advanced features of Postgresql could help in this situation. Regards, Philippe Lang ---(end of broadcast)--- TIP 5: don't forget to increase your free space map settings
Re: [SQL] "Subquery must return only one column" & query optimization
[email protected] wrote: > "Philippe Lang" writes: >> I was trying to run this query this morning: > >> -- >> SELECT > >> r.*, > >> ( >> SELECT > >> rl.reminder_header, >> rl.reminder_footer > >> FROM reminder_levels AS rl >> WHERE rl.lookup = >> ( >> SELECT MAX(reminder_level_lookup) >> FROM reminders >> WHERE customer_id = r.customer_id >> ) >> ) > >> FROM reminders AS r >> -- > >> Postgresql replied that: > >> -- >> ERROR: subquery must return only one column > > Since 8.0 or so you could write the sub-select as > > SELECT ROW(rl.reminder_header, rl.reminder_footer) FROM ... > > We ought to make that happen automatically, but it's not real high on > the to-do list. Hi Tom, Fine, the query is faster now: SELECT r.*, ( SELECT ROW(rl.reminder_header, rl.reminder_header) FROM reminder_levels AS rl WHERE rl.lookup = ( SELECT MAX(reminder_level_lookup) FROM reminders WHERE customer_id = r.customer_id ) ) AS rec FROM reminders AS r ... but the last column is now of type "record", and since this query serves as a datasource for a MS Access report, it is not able to "split" the record into the values that interest me: reminder_header and reminder_footer! Regards, Philippe Lang -- Sent via pgsql-sql mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql
[SQL] "Subquery must return only one column" & query optimization
Hi, I was trying to run this query this morning: -- SELECT r.*, ( SELECT rl.reminder_header, rl.reminder_footer FROM reminder_levels AS rl WHERE rl.lookup = ( SELECT MAX(reminder_level_lookup) FROM reminders WHERE customer_id = r.customer_id ) ) FROM reminders AS r -- Postgresql replied that: -- ERROR: subquery must return only one column SQL state: 42601 -- Is there a way to avoid writing: -- SELECT r.*, ( SELECT rl.reminder_header FROM reminder_levels AS rl WHERE rl.lookup = ( SELECT MAX(reminder_level_lookup) FROM reminders WHERE customer_id = r.customer_id ) ) AS reminder_header, ( SELECT rl.reminder_footer FROM reminder_levels AS rl WHERE rl.lookup = ( SELECT MAX(reminder_level_lookup) FROM reminders WHERE customer_id = r.customer_id ) ) AS reminder_footer FROM reminders AS r -- ... which works, but runs twice the same subselect block: -- FROM reminder_levels AS rl WHERE rl.lookup = ( SELECT MAX(reminder_level_lookup) FROM reminders WHERE customer_id = r.customer_id ) -- Thanks, Philippe Lang -- Sent via pgsql-sql mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql
