Re: [SQL] Slow Query problem

2008-01-29 Thread Premsun Choltanwanich


I already install the latest version of PostgreSQL on my machine then try again. I found that it has a little improvement about 0.5 second but I think it still slow.
 
What is the 'more detail' you need?
 
Any other advise?
 
 
 
>>> Tom Lane <[EMAIL PROTECTED]> 1/29/2008 0:20 >>>Andreas Joseph Krogh <[EMAIL PROTECTED]> writes:> On Monday 28 January 2008 08:18:24 Premsun Choltanwanich wrote:>> I am currently using PostgreSQL database version 8.0.13.  My problem>> relates to a slow result when a query using a defined view joins to another>> table for a result.> It is very hard to help without you providing the schema for the tables/views> involved.One suggestion is that 8.2.x is significantly smarter about joins tounions than previous releases were.  Whether this would help in yourparticular case is impossible to say, though, without more detail.regards, tom lane---(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


  NETsolutions Asia 
  Limited 


  +66 (2) 237 7247 



  

  


Re: [SQL] Slow Query problem

2008-01-29 Thread Andreas Joseph Krogh
On Tuesday 29 January 2008 09:18:00 Premsun Choltanwanich wrote:
> I already install the latest version of PostgreSQL on my machine then try
> again. I found that it has a little improvement about 0.5 second but I
> think it still slow.
>
> What is the 'more detail' you need?

Your tables, views and index definitions.

> Any other advise?

You haven't provided any information on how your tables/views look like and 
what indexes you have defined. A rule of thumb is to define an index for each 
column you join on.

-- 
Andreas Joseph Krogh <[EMAIL PROTECTED]>
Senior Software Developer / Manager
+-+
OfficeNet AS| The most difficult thing in the world is to |
Karenslyst Allé 11  | know how to do a thing and to watch |
PO. Box 529 Skøyen  | somebody else doing it wrong, without   |
0214 Oslo   | comment.|
NORWAY  | |
Tlf:+47 24 15 38 90 | |
Fax:+47 24 15 38 91 | |
Mobile: +47 909  56 963 | |
+-+

---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings


[SQL] Slow GROUP BY query

2008-01-29 Thread Stuart Brooks

I have a very simple table set:

Transactions:
transaction_key PRIMARY KEY
client TEXT
time TIMESTAMP

LineItems
transaction_key INT
amount INT

A query to print the contents of transactions with a sum of the line 
item amounts provides a very suboptimal result. The problem seems to be 
the GROUP BY clause as it doesn't use the primary index. Rewriting the 
query to only group on the transaction_key and returning the max of the 
other transaction fields results in a query of <1ms. (see queries below)


Can anyone shed any light here, I would have expected the queries to 
take roughly the same time?


Out of interest, since we are grouping by transaction_key which is 
unique, surely the other Transaction fields in the group by could be 
ignored by the planner?


Thanks
Stuart

(running postgresql 8.2.5 on NetBSD 3)


>> Slow query

EXPLAIN 
SELECT t.transaction_key,t.cashier,t.time,SUM(l.amount) 
FROM Transactions t JOIN LineItems l USING (transaction_key) 
GROUP BY t.transaction_key,t.cashier,t.time 
ORDER BY t.transaction_key;

   QUERY PLAN
---
Sort  (cost=449.16..454.16 rows=2000 width=32)
  Sort Key: t.transaction_key
  ->  HashAggregate  (cost=314.50..339.50 rows=2000 width=32)
->  Hash Join  (cost=66.00..262.07 rows=5243 width=32)
  Hash Cond: (l.transaction_key = t.transaction_key)
  ->  Seq Scan on lineitems l  (cost=0.00..117.43 rows=5243 
width=16)
  ->  Hash  (cost=41.00..41.00 rows=2000 width=24)
->  Seq Scan on transactions t  (cost=0.00..41.00 rows=2000 
width=24)
(8 rows)



Fast query


EXPLAIN 
SELECT t.transaction_key,MAX(t.cashier),MAX(t.time),SUM(l.amount) 
FROM Transactions t JOIN LineItems l USING (transaction_key) 
GROUP BY t.transaction_key 
ORDER BY t.transaction_key;


  QUERY PLAN
-
GroupAggregate  (cost=0.00..459.11 rows=2000 width=32)
  ->  Merge Join  (cost=0.00..371.68 rows=5243 width=32)
Merge Cond: (t.transaction_key = l.transaction_key)
->  Index Scan using transactions_pkey on transactions t  
(cost=0.00..86.25 rows=2000 width=24)
->  Index Scan using lineitems_transaction_index on lineitems l  
(cost=0.00..214.90 rows=5243 width=16)
(5 rows)




---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

  http://www.postgresql.org/docs/faq


[SQL] JOINing SET returning function.

2008-01-29 Thread Dawid Kuroczko
Hi,

I have a set returning function returning variable number of rows
(RETURNS SETOF RECORD).

I have a table which contains a list of input values for this SRF.

I want to write SQL which will return all the data found there.  A
simple test case:

a tble
CREATE TEMP TABLE list (n int);
INSERT INTO list VALUES (1),(3),(5),(6);

CREATE OR REPLACE FUNCTION test_set (IN OUT n int, OUT bar text)
RETURNS SETOF RECORD AS $$
  my $n = shift;
  for my $x (1..$n) {
return_next { n=> $x, bar => '#' x $x }
  };
  return undef;
$$ LANGUAGE PLperl;

Now, this works fine:

SELECT select * from test_set(4);

n | bar
---+--
 1 | #
 2 | ##
 3 | ###
 4 | 

And this works fine too:
SELECT generate_series(1,n) FROM list;
 generate_series
-
   1
   1
   2
   3
   1
   2
   3
   4
   5
   1
   2
   3
   4
   5
   6

However I would like to write a code which will work with test_set()
as it does with generate_series:

SELECT test_set(n) FROM list;
ERROR:  set-valued function called in context that cannot accept a set

...for which I've tried subselects and JOINs but somehow I fail to
make it work, for instance:
SELECT * FROM list, test_set(n);
ERROR:  function expression in FROM may not refer to other relations
of same query level

Is there an obvious solution (except wrapping it in some PL function)?

If it is not clear unitl that point, I want to do equivalent of:

SELECT * FROM test_set(1)
  UNION ALL SELECT * FROM test_set(3)
  UNION ALL SELECT * FROM test_set(5)
  UNION ALL SELECT * FROM test_set(6);

...except dynamically using "n" column from "list" table.

Of course this is a test case, not the original problem. :-)

 Regards,
Dawid

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [SQL] Slow Query problem

2008-01-29 Thread Premsun Choltanwanich


SQL I use for create related table and view:
 
 
CREATE TABLE t_payment_detail(  "sysid" bigserial NOT NULL,  receiptno varchar(10) NOT NULL,  refpath varchar(255) NOT NULL,  refno varchar(100) NOT NULL,  CONSTRAINT t_payment_detail_pkey PRIMARY KEY ("sysid")) WITHOUT OIDS;
 
CREATE TABLE t_receipt_cancel(  receiptsysid int8 NOT NULL,  amount float8 NOT NULL,  receiptcomment varchar(255) NOT NULL,  CONSTRAINT t_receipt_cancel_pkey PRIMARY KEY (receiptsysid)) WITH OIDS;
 
CREATE TABLE t_charge(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  chargelistsysid int8 NOT NULL,  refno varchar(20) NOT NULL,  chargedate timestamp NOT NULL,  quantity float8 NOT NULL,  unitprice float8 NOT NULL,  amount float8 NOT NULL,  vat float8 NOT NULL,  service float8 NOT NULL,  CONSTRAINT t_charge_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE TABLE t_posbill(  "sysid" bigserial NOT NULL,  billno varchar(20) NOT NULL DEFAULT ''::character varying,  billdate timestamp NOT NULL DEFAULT '1601-01-01 00:00:00'::timestamp without time zone,  mbrsysid int8 NOT NULL DEFAULT 0,  totalamount float8 NOT NULL DEFAULT 0,  totalvat float8 NOT NULL DEFAULT 0,  totalservice float8 NOT NULL DEFAULT 0,  CONSTRAINT t_posbill_pkey PRIMARY KEY ("sysid")) WITHOUT OIDS;
 
 
 
CREATE TABLE t_creditnotes(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  chargelistsysid int8 NOT NULL,  chitno varchar(20) NOT NULL,  chitdate timestamp NOT NULL,  refno varchar(20) NOT NULL,  chargedate timestamp NOT NULL,  quantity float8 NOT NULL,  unitprice float8 NOT NULL,  amount float8 NOT NULL,  vat float8 NOT NULL,  service float8 NOT NULL,  CONSTRAINT t_creditnotes_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
 
 
CREATE TABLE t_invoice(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  chargelistsysid int8 NOT NULL,  invno varchar(50) NOT NULL,  invdate timestamp NOT NULL,  totalvalue float8 NOT NULL,  totalvat float8 NOT NULL,  totalservice float8 NOT NULL,  CONSTRAINT t_invoice_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE TABLE t_receipt(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  receiptno varchar(10) NOT NULL,  receiptdate timestamp NOT NULL,  paymethod varchar(30) NOT NULL,  amount float8 NOT NULL,  flagprint bool NOT NULL DEFAULT false,  CONSTRAINT t_receipt_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE TABLE t_moneytransfer(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  transferno varchar(10) NOT NULL,  transferdate timestamp NOT NULL,  transferamount float8 NOT NULL,  CONSTRAINT t_moneytransfer_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
 
 
CREATE TABLE t_carryforward(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  cfno varchar(10) NOT NULL,  cfdate timestamp NOT NULL,  amount float8 NOT NULL,  CONSTRAINT t_carryforward_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE OR REPLACE VIEW v_invtransaction_main AS ( SELECT 'C'::text || t_charge.refno::text AS transinvno, t_charge.mbrsysid, 'CHIT'::text AS particular, t_charge.chargedate AS transdate, sum(t_charge.amount) AS totamount, sum(t_charge.vat) AS totvat, sum(t_charge.service) AS totservice, 'Dr' AS cr_dr, t_charge.refno AS transrefno   FROM t_charge  GROUP BY 'C'::text || t_charge.refno::text, t_charge.mbrsysid,  'CHIT'::text , t_charge.chargedate, t_charge.refnoUNION ALL  SELECT 'B'::text || t_posbill.billno::text AS transinvno, t_posbill.mbrsysid, 'POS'::text AS particular, t_posbill.billdate AS transdate, t_posbill.totalamount AS totamount, t_posbill.totalvat AS totvat, t_posbill.totalservice AS totservice, 'Dr' AS cr_dr, t_posbill.billno AS transrefno   FROM t_posbill)UNION ALL  SELECT 'CN'::text || t_creditnotes.refno::text AS transinvno, t_creditnotes.mbrsysid, 'Credit Note'::text AS particular, t_creditnotes.chargedate AS transdate, - sum(t_creditnotes.amount) AS totamount, - sum(t_creditnotes.vat) AS totvat, - sum(t_creditnotes.service) AS totservice, 'Cr' AS cr_dr, t_creditnotes.refno AS transrefno   FROM t_creditnotes  GROUP BY 'CN'::text || t_creditnotes.refno::text, t_creditnotes.mbrsysid, 'Credit Note'::text, t_creditnotes.chargedate, t_creditnotes.refno)UNION ALL  SELECT 'I'::text || t_invoice.invno::text AS transinvno, t_invoice.mbrsysid, 'Monthly Invoice '::text AS particular, t_invoice.invdate AS transdate, sum(t_invoice.totalvalue) AS totamount, sum(t_invoice.totalvat) AS totvat, sum(t_invoice.totalservice) AS totservice, 'Dr' AS cr_dr, t_invoice.invno AS transrefno   FROM t_invoice  GROUP BY 'I'::text || t_invoice.invno::text, t_invoice.mbrsysid, 'Monthly Invoice'::text, t_invoice.invdate,t_invoice.invno)UNION ALL  SELECT 'P'::text || t_receipt.receiptno::text AS transinvno, t_receipt.mbrsysid, t_receipt.paymethod::text AS particular, t_receipt.receiptdate AS transdate, t_receipt.amount * (- 1::double precision) AS totamount, '0' AS totvat, '0' AS totservice, 'Cr' AS cr_dr, t_receipt.receiptno AS transrefno   FROM t_receipt  WHERE NOT (t_receipt."sysid" IN ( SELECT t_receipt_cancel.receiptsysid FROM t_receipt_cancel)))UNION ALL  SEL

Re: [SQL] Slow Query problem

2008-01-29 Thread Premsun Choltanwanich


SQL I use for create related table and view:
 
 
CREATE TABLE t_payment_detail(  "sysid" bigserial NOT NULL,  receiptno varchar(10) NOT NULL,  refpath varchar(255) NOT NULL,  refno varchar(100) NOT NULL,  CONSTRAINT t_payment_detail_pkey PRIMARY KEY ("sysid")) WITHOUT OIDS;
 
CREATE TABLE t_receipt_cancel(  receiptsysid int8 NOT NULL,  amount float8 NOT NULL,  receiptcomment varchar(255) NOT NULL,  CONSTRAINT t_receipt_cancel_pkey PRIMARY KEY (receiptsysid)) WITH OIDS;
 
CREATE TABLE t_charge(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  chargelistsysid int8 NOT NULL,  refno varchar(20) NOT NULL,  chargedate timestamp NOT NULL,  quantity float8 NOT NULL,  unitprice float8 NOT NULL,  amount float8 NOT NULL,  vat float8 NOT NULL,  service float8 NOT NULL,  CONSTRAINT t_charge_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE TABLE t_posbill(  "sysid" bigserial NOT NULL,  billno varchar(20) NOT NULL DEFAULT ''::character varying,  billdate timestamp NOT NULL DEFAULT '1601-01-01 00:00:00'::timestamp without time zone,  mbrsysid int8 NOT NULL DEFAULT 0,  totalamount float8 NOT NULL DEFAULT 0,  totalvat float8 NOT NULL DEFAULT 0,  totalservice float8 NOT NULL DEFAULT 0,  CONSTRAINT t_posbill_pkey PRIMARY KEY ("sysid")) WITHOUT OIDS;
 
 
 
CREATE TABLE t_creditnotes(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  chargelistsysid int8 NOT NULL,  chitno varchar(20) NOT NULL,  chitdate timestamp NOT NULL,  refno varchar(20) NOT NULL,  chargedate timestamp NOT NULL,  quantity float8 NOT NULL,  unitprice float8 NOT NULL,  amount float8 NOT NULL,  vat float8 NOT NULL,  service float8 NOT NULL,  CONSTRAINT t_creditnotes_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
 
 
CREATE TABLE t_invoice(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  chargelistsysid int8 NOT NULL,  invno varchar(50) NOT NULL,  invdate timestamp NOT NULL,  totalvalue float8 NOT NULL,  totalvat float8 NOT NULL,  totalservice float8 NOT NULL,  CONSTRAINT t_invoice_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE TABLE t_receipt(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  receiptno varchar(10) NOT NULL,  receiptdate timestamp NOT NULL,  paymethod varchar(30) NOT NULL,  amount float8 NOT NULL,  flagprint bool NOT NULL DEFAULT false,  CONSTRAINT t_receipt_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE TABLE t_moneytransfer(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  transferno varchar(10) NOT NULL,  transferdate timestamp NOT NULL,  transferamount float8 NOT NULL,  CONSTRAINT t_moneytransfer_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
 
 
CREATE TABLE t_carryforward(  "sysid" bigserial NOT NULL,  mbrsysid int8 NOT NULL,  cfno varchar(10) NOT NULL,  cfdate timestamp NOT NULL,  amount float8 NOT NULL,  CONSTRAINT t_carryforward_pkey PRIMARY KEY ("sysid")) WITH OIDS;
 
CREATE OR REPLACE VIEW v_invtransaction_main AS ( SELECT 'C'::text || t_charge.refno::text AS transinvno, t_charge.mbrsysid, 'CHIT'::text AS particular, t_charge.chargedate AS transdate, sum(t_charge.amount) AS totamount, sum(t_charge.vat) AS totvat, sum(t_charge.service) AS totservice, 'Dr' AS cr_dr, t_charge.refno AS transrefno   FROM t_charge  GROUP BY 'C'::text || t_charge.refno::text, t_charge.mbrsysid,  'CHIT'::text , t_charge.chargedate, t_charge.refnoUNION ALL  SELECT 'B'::text || t_posbill.billno::text AS transinvno, t_posbill.mbrsysid, 'POS'::text AS particular, t_posbill.billdate AS transdate, t_posbill.totalamount AS totamount, t_posbill.totalvat AS totvat, t_posbill.totalservice AS totservice, 'Dr' AS cr_dr, t_posbill.billno AS transrefno   FROM t_posbill)UNION ALL  SELECT 'CN'::text || t_creditnotes.refno::text AS transinvno, t_creditnotes.mbrsysid, 'Credit Note'::text AS particular, t_creditnotes.chargedate AS transdate, - sum(t_creditnotes.amount) AS totamount, - sum(t_creditnotes.vat) AS totvat, - sum(t_creditnotes.service) AS totservice, 'Cr' AS cr_dr, t_creditnotes.refno AS transrefno   FROM t_creditnotes  GROUP BY 'CN'::text || t_creditnotes.refno::text, t_creditnotes.mbrsysid, 'Credit Note'::text, t_creditnotes.chargedate, t_creditnotes.refno)UNION ALL  SELECT 'I'::text || t_invoice.invno::text AS transinvno, t_invoice.mbrsysid, 'Monthly Invoice '::text AS particular, t_invoice.invdate AS transdate, sum(t_invoice.totalvalue) AS totamount, sum(t_invoice.totalvat) AS totvat, sum(t_invoice.totalservice) AS totservice, 'Dr' AS cr_dr, t_invoice.invno AS transrefno   FROM t_invoice  GROUP BY 'I'::text || t_invoice.invno::text, t_invoice.mbrsysid, 'Monthly Invoice'::text, t_invoice.invdate,t_invoice.invno)UNION ALL  SELECT 'P'::text || t_receipt.receiptno::text AS transinvno, t_receipt.mbrsysid, t_receipt.paymethod::text AS particular, t_receipt.receiptdate AS transdate, t_receipt.amount * (- 1::double precision) AS totamount, '0' AS totvat, '0' AS totservice, 'Cr' AS cr_dr, t_receipt.receiptno AS transrefno   FROM t_receipt  WHERE NOT (t_receipt."sysid" IN ( SELECT t_receipt_cancel.receiptsysid FROM t_receipt_cancel)))UNION ALL  SEL

[SQL] Re: Proposed archival read only trigger on rows - prevent history modification

2008-01-29 Thread Steve Midgley

At 07:50 PM 1/29/2008, [EMAIL PROTECTED] wrote:

Date: Mon, 28 Jan 2008 20:16:35 -0800
From: Bryce Nesbitt <[EMAIL PROTECTED]>
To: pgsql-sql@postgresql.org
Subject: Proposed archival read only trigger on rows - prevent history 
modification

[snip]
I'm considering building a protective mechanism, and am seeking 
feedback

on the idea.  The approach would be to add a new column named "ro" to
each table at invoice level and below.  Then have a trigger on
'ro'==true deny the write, and probably raise a huge stink.  As 
invoice
are mailed each month, all the supporting data would be set to "ro" 
true.

[snip]


Hi Bryce,

I have a similar situation but a little in reverse. I have many sets of 
*incoming* records, which I want to preserve, though at any one time 
there is only one "live" version of the incoming records. Sometimes I 
have to read and compare versions of the records, live or otherwise. 
The logical records I'm talking about occupy a number of tables that 
are joined together in the database itself.


My solution, which required a little middleware engineering, was to 
create two tables for each table that had multiple "versions" of 
records. So, I have  a "property" table and a "property_versions" table 
that have identical table structures. I have a column common to every 
such versioned set of tables called "import_group_id." For live tables, 
this just tells me which version from the "*_versions" table is 
currently being used for that row. The live tables have primary keys 
just like normal ("id" as a serial int field). The "versions" tables' 
primary keys are different, compound keyed off "id" and 
"import_group_id." This permits normalization but also allows multiple 
versions of the same records.


In your case, I'd say you could archive your data table to a 
"data_versions" table. You might archive periodically and leave the 
records on the live table (but knowing that audit versions are safely 
tucked away and easily accessible/comparable), or you might migrate the 
records off the live table onto the versions table (insert followed by 
a delete in a transaction). If you adopted the latter method, you could 
union the two tables to get a complete set of rows. (Via a view even? 
Not sure if you can create a view on a union but it seems likely you 
can..)


You could also choose (like I did) to store multiple versions of the 
records, if your data are slowly changing rather than completely 
unchanging. However it sounds like your situation is such that you want 
to ensure old records are not modified ever. If you set up triggers 
and/or permission on the "data_versions" table, no one can ever delete 
or modify anything there. This might work perfectly for your purposes. 
Data in the live table can be edited as you like but changes to the 
"data_versions" table is simply not permitted. Inserts are allowed to 
data_versions but nothing else..


I hope this idea is useful. If I haven't explained it well, drop me a 
line and I'll try to clarify. Good luck with the project!


Steve


---(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