tags:

views:

145

answers:

2

I want to try to update a postgresql table with it's own values.

This table contains an overview of the products sold by year and month.

CREATE TABLE sales
(
  sector character(3),
  brand character(4),
  product character(16),
  syear integer,
  smonth integer,
  units_sold integer,
  units_sold_year integer,
  CONSTRAINT pk_sales_id PRIMARY KEY (sector, brand, product, syear, smonth)
);

INSERT INTO sales(sector, brand, product, syear, smonth, units_sold, units_sold_year) VALUES ('1', 'ABE', '71012', 2010, 0, 9, 0); /* The month 0 is the whole year */
INSERT INTO sales(sector, brand, product, syear, smonth, units_sold, units_sold_year) VALUES ('1', 'ABE', '71012', 2010, 1, 4, 0);
INSERT INTO sales(sector, brand, product, syear, smonth, units_sold, units_sold_year) VALUES ('1', 'ABE', '71012', 2010, 2, 5, 0);
INSERT INTO sales(sector, brand, product, syear, smonth, units_sold, units_sold_year) VALUES ('ALL', 'ABE', '71012', 2010, 0, 9, 10);
...

I've added the column 'units_sold_year' because I need to be able to do very quick requests on this table (I'd otherwise have to do subquerys) and I'm trying to fill it.

Here's the update request I've built so far but it seems to run in an infinite loop :

UPDATE sales set units_sold_year = (SELECT units_sold_year FROM sales as s WHERE sector = 'ALL' and s.smonth = 0 and s.brand = su.brand and s.product = su.product and s.syear = su.syear)
FROM sales su
where su.syear = 2010
and su.brand = 'ABE' and su.product = '71012';

Is it possile to update a table with its own rows like this ?

+2  A: 

Your query looks good (even if I disagree with the requirement)

I would change the order of your subquery, though, to match your PRIMARY KEY index. I believe that with a compound index like what you have, Postgres will evaluate in order of the index.

So your PK index is:

(sector, brand, product, syear, smonth)

and your subquery should be:

...WHERE sector = 'ALL' and s.brand = su.brand and s.product = su.product and s.syear = su.syear and s.smonth = 0...

With composite indexes, order matters for queries.

If you have a composite index on columns (col0, col1, col2), this index will benefit queries that do:

select * from tablex where col0 = a
select * from tablex where col0 = a and col1 = b
select * from tablex where col0 = a and col1 = b and col2 = c

but it will not be used for a query that does:

select * from tablex where col1=b and col2=c

So it would be redundant (and probably performance impeding) to create indexes on (col0), (col0, col1), and (col0, col1, col2).

Tim Drisdelle
Yeah, further explanation regarding composite indexes in Postgres...Your composite index (sector, brand, product, syear, smonth) will be used for queries that do WHERE "sector", "sector, brand", "sector, brand, product" will all use that index.But if you were to query WHERE "sector, product, brand" (notice order is different from the index?), the composite index would not be used.
Tim Drisdelle
You mean that I should change the order of the WHERE in order to benefit the composite index ?Your PK seems to be the same, am I missing something ?
kevin
That's exactly what I mean.(will update answer)
Tim Drisdelle
Thanks ! Could you elaborate on why you "disagree with the requirement" ?How would you improve my current setup ?
kevin
Sure. I added that little caveat only because I don't think a fair answer is to say "well that's a foolish idea". Better to just answer the question :)Why I disagree with the requirement? Well, it sounds like this "sales" table should represent just pure sales. The aggregation of these values into some sort of reportable data should not muddy the raw data beneath it. It is fragile.Better to create a separate data VIEW, or just leave it as a reporting query.
Tim Drisdelle
Ok thanks that's fair, it's true that this design is fragile if anything changes. This "sales" table only exists to generate statistical data that must produce super fast results and right now the users can create small custom querys with instant display.What do you call a "reporting query" ?
kevin
A: 

The rest of the answers are great, but one thing I noticed is that you are using char(n). Generally that is a bad data type to use because it pads out. Consider using varchar instead.

Joshua D. Drake