Re: [SQL] Counting days ...

2008-03-14 Thread Aarni Ruuhimäki
>
> Check my work, but I think the sum part of the query simply becomes:
>
> sum (
>   (
>   date_smaller(res_end_day, '2008-02-29'::date) -
>   date_larger(res_start_day, '2008-01-31'::date)
>   ) * group_size
> )
>
> Basically remove the "+1" so we don't include both start and end dates
> but move the start base back one day so anyone starting prior to Feb 1
> gets the extra day added.
>
> Cheers,
> Steve

Thanks Steve,

I'm not sure if I quite grasped this. It gives a bit funny results:

SELECT sum ((date_smaller(res_end_day, '2007-12-31'::date) - 
date_larger(res_start_day, '2006-12-31'::date)) * group_size) AS 
days_in_period,
c.country_name AS country
FROM product_res pr
LEFT JOIN countries c ON pr.country_id = c.country_id
WHERE group_id = 1 AND res_end_day >= '2007-01-01' AND res_end_day <= 
'2008-12-31' group by pr.country_id, c.country_name;
 days_in_period |  country
+
-441137 |
-30 | Germany
-28 | Estonia
 60 | Bulgaria
 -25003 | Russian Federation
-207670 | Suomi
256 | Ukraine
  -6566 | Latvia
   -280 | United States
  -1889 | Switzerland
114 | Lithuania
 36 | Norway
-66 | Sweden
170 | Kazakhstan
 72 | Belarus
(15 rows)

Anyway, I have to rethink and elaborate the query. I know that it will usually 
be on a monthly or yearly basis, but a reservation can actually be any of the 
following in relation to the given (arbitrary) period:

1. start_day before period_start, end_day = period_start

2. start_day before period_start, end_day in period

3. start_day before period_start, end_day = period_end

4. start_day = period_start, end_day in period

5. start_day in period, end_day in period

6. start_day = period_start, end_day = period_end

7. start_day in period, end_day = period_end

8. start_day in period, end_day after period_end

9. start_day = period_start, end_day = period_end

10 start_day before period_start, end_day after period_end

Hmm ...

Best regards,
-- 
Aarni Ruuhimäki
---
Burglars usually come in through your windows.
---

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] Counting days ...

2008-03-14 Thread Frank Bax

Aarni Ruuhimäki wrote:

Check my work, but I think the sum part of the query simply becomes:

sum (
  (
  date_smaller(res_end_day, '2008-02-29'::date) -
  date_larger(res_start_day, '2008-01-31'::date)
  ) * group_size
)

Basically remove the "+1" so we don't include both start and end dates
but move the start base back one day so anyone starting prior to Feb 1
gets the extra day added.

Cheers,
Steve


Thanks Steve,

I'm not sure if I quite grasped this. It gives a bit funny results:

SELECT sum ((date_smaller(res_end_day, '2007-12-31'::date) - 
date_larger(res_start_day, '2006-12-31'::date)) * group_size) AS 
days_in_period,

c.country_name AS country
FROM product_res pr
LEFT JOIN countries c ON pr.country_id = c.country_id
WHERE group_id = 1 AND res_end_day >= '2007-01-01' AND res_end_day <= 
'2008-12-31' group by pr.country_id, c.country_name;

 days_in_period |  country
+
-441137 |
-30 | Germany
-28 | Estonia
 60 | Bulgaria
 -25003 | Russian Federation
-207670 | Suomi
256 | Ukraine
  -6566 | Latvia
   -280 | United States
  -1889 | Switzerland
114 | Lithuania
 36 | Norway
-66 | Sweden
170 | Kazakhstan
 72 | Belarus
(15 rows)

Anyway, I have to rethink and elaborate the query. I know that it will usually 
be on a monthly or yearly basis, but a reservation can actually be any of the 
following in relation to the given (arbitrary) period:


1. start_day before period_start, end_day = period_start
2. start_day before period_start, end_day in period
3. start_day before period_start, end_day = period_end
4. start_day = period_start, end_day in period
5. start_day in period, end_day in period
6. start_day = period_start, end_day = period_end
7. start_day in period, end_day = period_end
8. start_day in period, end_day after period_end
9. start_day = period_start, end_day = period_end
10 start_day before period_start, end_day after period_end

Hmm ...

Best regards,




#6 and #9 are the same.  You missed these:

a   start_day before period_start, end_day before period_start
b   start_day = period_start, end_day = period_start
c   start_day = period_start, end_day after period_end
d   start_day = period_end, end_day = period_end
e   start_day = period_end, end_day after period_end
f   start_day after period_end, end_day after period_end

Granted, a & f should not match where clause; but then groups 10,c,e 
don't meet your where clause either.  Your where clause should probably be:


WHERE group_id = 1 AND (res_start_day >= '2007-01-01' AND res_end_day <= 
'2008-12-31')


Are you sure that your database does not have any rows where start_day 
is after end_day?  These rows could certainly skew results.


I would suggest that you identify a few rows that meet each of these 
conditions.  Change the where clause to select rows in one group at a 
time.  You might consider using a unique row identifier in where clause 
during these tests to make sure you are processing the rows you think 
you are.  When all test cases work properly; then run your generalized 
query again.


--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] Counting days ...

2008-03-14 Thread Frank Bax

Frank Bax wrote:

Aarni Ruuhimäki wrote:
Anyway, I have to rethink and elaborate the query. I know that it will 
usually be on a monthly or yearly basis, but a reservation can 
actually be any of the following in relation to the given (arbitrary) 
period:


1. start_day before period_start, end_day = period_start
2. start_day before period_start, end_day in period
3. start_day before period_start, end_day = period_end
4. start_day = period_start, end_day in period
5. start_day in period, end_day in period
6. start_day = period_start, end_day = period_end
7. start_day in period, end_day = period_end
8. start_day in period, end_day after period_end
9. start_day = period_start, end_day = period_end
10 start_day before period_start, end_day after period_end




#6 and #9 are the same.  You missed these:

astart_day before period_start, end_day before period_start
bstart_day = period_start, end_day = period_start
cstart_day = period_start, end_day after period_end
dstart_day = period_end, end_day = period_end
estart_day = period_end, end_day after period_end
fstart_day after period_end, end_day after period_end

Granted, a & f should not match where clause; but then groups 10,c,e 
don't meet your where clause either.  Your where clause should probably be:


WHERE group_id = 1 AND (res_start_day >= '2007-01-01' AND res_end_day <= 
'2008-12-31')


Are you sure that your database does not have any rows where start_day 
is after end_day?  These rows could certainly skew results.


I would suggest that you identify a few rows that meet each of these 
conditions.  Change the where clause to select rows in one group at a 
time.  You might consider using a unique row identifier in where clause 
during these tests to make sure you are processing the rows you think 
you are.  When all test cases work properly; then run your generalized 
query again.






Change 10,c,e to 8,10,c,e - Group 8 also does not meet your initial 
WHERE clause.  My suggestion for WHERE clause also does not work.  This 
might work better (although it still could be wrong):


WHERE group_id = 1 AND (res_start_day BETWEEN '2007-01-01' AND 
'2008-12-31' OR res_end_day BETWEEN '2007-01-01' AND '2008-12-31')


In case I still have it wrong, try each test group separately and you'll 
soon find out if the WHERE clause is correct or not.


--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] Counting days ...

2008-03-14 Thread Aarni Ruuhimäki
Thanks Frank,

Top and between posting ...

On Friday 14 March 2008 15:58, Frank Bax wrote:
> Frank Bax wrote:
> > Aarni Ruuhimäki wrote:
> >> Anyway, I have to rethink and elaborate the query. I know that it will
> >> usually be on a monthly or yearly basis, but a reservation can
> >> actually be any of the following in relation to the given (arbitrary)
> >> period:
> >>
> >> 1. start_day before period_start, end_day = period_start
> >> 2. start_day before period_start, end_day in period
> >> 3. start_day before period_start, end_day = period_end
> >> 4. start_day = period_start, end_day in period
> >> 5. start_day in period, end_day in period
> >> 6. start_day = period_start, end_day = period_end
> >> 7. start_day in period, end_day = period_end
> >> 8. start_day in period, end_day after period_end
> >> 9. start_day = period_start, end_day = period_end
> >> 10 start_day before period_start, end_day after period_end
> >
> > #6 and #9 are the same.  You missed these:

Whoops, 9 should be c.

> >
> > astart_day before period_start, end_day before period_start

This I don't have to care about as it is not in the period we are looking at.

> > bstart_day = period_start, end_day = period_start

Is zero days/nights, ignored. Not even possible to insert in the application. 
end_day must be greater than start_day.

> > cstart_day = period_start, end_day after period_end

Yes. Number 9 now.

> > dstart_day = period_end, end_day = period_end

Is zero days, ignored. like b.

> > estart_day = period_end, end_day after period_end

Is outside the period. Day changes / the night starts at midnight, so this 
would go in the 'next' period. Like number 1 comes in this period as one day.

> > fstart_day after period_end, end_day after period_end

This is also outside the period we are looking at.

> >
> > Granted, a & f should not match where clause; but then groups 10,c,e
> > don't meet your where clause either.  Your where clause should probably
> > be:
> >
> > WHERE group_id = 1 AND (res_start_day >= '2007-01-01' AND res_end_day <=
> > '2008-12-31')
> >
> > Are you sure that your database does not have any rows where start_day
> > is after end_day?  These rows could certainly skew results.

Yes, the application does not allow this.
SELECT res_id FROM product_res WHERE res_start_day > res_end_day;
 res_id

(0 rows)

> >
> > I would suggest that you identify a few rows that meet each of these
> > conditions.  Change the where clause to select rows in one group at a
> > time.  You might consider using a unique row identifier in where clause
> > during these tests to make sure you are processing the rows you think
> > you are.  When all test cases work properly; then run your generalized
> > query again.
>
> Change 10,c,e to 8,10,c,e - Group 8 also does not meet your initial
> WHERE clause.  My suggestion for WHERE clause also does not work.  This
> might work better (although it still could be wrong):
>
> WHERE group_id = 1 AND (res_start_day BETWEEN '2007-01-01' AND
> '2008-12-31' OR res_end_day BETWEEN '2007-01-01' AND '2008-12-31')
>
> In case I still have it wrong, try each test group separately and you'll
> soon find out if the WHERE clause is correct or not.

I think I need more ORs in the WHERE clause to find all res_ids I want to 
count according to the 10 rules. Ie. if one or more days of a reservation is 
'inside' the given period.

Testing ...

Best regards,

-- 
Aarni Ruuhimäki
---
Burglars usually come in through your windows.
---

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] Counting days ...

2008-03-14 Thread Frank Bax

Aarni Ruuhimäki wrote:

Thanks Frank,


astart_day before period_start, end_day before period_start


This I don't have to care about as it is not in the period we are looking at.


bstart_day = period_start, end_day = period_start


Is zero days/nights, ignored. Not even possible to insert in the application. 
end_day must be greater than start_day.



You should still consider rows that are "out of range" or "zero nights" 
in your test cases to make sure your report processes them correctly.


--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] Counting days ...

2008-03-14 Thread Steve Crawford

Aarni Ruuhimäki wrote:


Thanks Steve,

I'm not sure if I quite grasped this. It gives a bit funny results:

SELECT sum ((date_smaller(res_end_day, '2007-12-31'::date) - 
date_larger(res_start_day, '2006-12-31'::date)) * group_size) AS 
days_in_period,

c.country_name AS country
FROM product_res pr
LEFT JOIN countries c ON pr.country_id = c.country_id
WHERE group_id = 1 AND res_end_day >= '2007-01-01' AND res_end_day <= 
'2008-12-31' group by pr.country_id, c.country_name;

 days_in_period |  country
+
-441137 |
-30 | Germany
-28 | Estonia
...


I see one error in my logic. It doesn't account for the situation where 
res_end_day is prior to the start of the period you are viewing. You can 
fix this by limiting records with the appropriate where-clause or by 
wrapping the date_smaller inside a date_larger (and vice-versa) to 
ensure that all dates stay inside the desired period.


Or you can fix it by using an appropriate where-clause. Yours appears 
broken - I think you want res_end_day >2006-12-31 (or >=2007-01-01 - I 
prefer mine as you can use the same date in multiple places in the 
query) which is what you have.


But I think you want the end of period to be limited to res_start_day 
<=2007-12-31.


IOW, if your *end* date is *before* the period of interest or your 
*start* date is *after* the period of interest, skip the record.


My guess is that you have records with res_start_day > 2007-12-31. After 
applying the larger and smaller functions, this will end up with a 
res_end_day of 2007-12-31 giving an end_day < start_day.


(I'm presuming you have appropriate constraints to prevent end_day from 
being earlier than start_day. If not, check for that and add the 
constraints.)


Cheers,
Steve

--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


[SQL] DB Design

2008-03-14 Thread PostgreSQL Admin
I have a inventory system design in which I would like some help with to 
see if it's efficient.  The products are broken into:


Product tables
Property tables
Configurable Products - this would include colors (i.e. - black, blue 
and green) tied to products


I'm thinking of breaking inventory into 2 tables.

Product Inventory
Inventory Adjustment

Should I include the fk of the Configurable Product in the above tables 
or break it out further into more tables?


Product Inventory
Inventory Adjustment
--plus--
Product  Property Inventory
Inventory Property Adjustment

Thanks for any input,
J

These are my Product tables:

\d cart_product
  Table "public.cart_product"
 Column   |   Type   | 
Modifiers
---+--+---
id| integer  | not null default 
nextval('cart_product_id_seq'::regclass)

name  | character varying(128)   | not null
kind  | character varying(40)|
sku   | character varying(15)|
short_description | character varying(255)   | not null
description   | text |
category_id   | integer  | not null
date_created  | timestamp with time zone | not null
active| boolean  | not null
in_stock  | boolean  | not null
featured  | boolean  | not null
ordering  | integer  |
Indexes:
   "cart_product_pkey" PRIMARY KEY, btree (id)
   "cart_product_category_id" btree (category_id)
Foreign-key constraints:
   "cart_product_category_id_fkey" FOREIGN KEY (category_id) REFERENCES 
cart_category(id) DEFERRABLE INITIALLY DEFERRED



\d cart_propertyvariation
   Table "public.cart_propertyvariation"
   Column | Type  |  
Modifiers 
---+---+-
id| integer   | not null default 
nextval('cart_propertyvariation_id_seq'::regclass)

properties_id | integer   | not null
name  | character varying(42) | not null
value | character varying(20) | not null
order | integer   |
Indexes:
   "cart_propertyvariation_pkey" PRIMARY KEY, btree (id)
   "cart_propertyvariation_properties_id" btree (properties_id)
Check constraints:
   "cart_propertyvariation_order_check" CHECK ("order" >= 0)
Foreign-key constraints:
   "properties_id_refs_id_73bc0a59" FOREIGN KEY (properties_id) 
REFERENCES cart_property(id) DEFERRABLE INITIALLY DEFERRED



\d cart_configurableproduct
   Table "public.cart_configurableproduct"
Column  | Type |   
Modifiers  
-+--+---
id  | integer  | not null default 
nextval('cart_configurableproduct_id_seq'::regclass)

product_id  | integer  | not null
variation_id| integer  | not null
price_change| numeric(8,2) |
weight_change   | integer  |
quantity_change | integer  |
active  | boolean  | not null
Indexes:
   "cart_configurableproduct_pkey" PRIMARY KEY, btree (id)
   "cart_configurableproduct_product_id" btree (product_id)
   "cart_configurableproduct_variation_id" btree (variation_id)
Foreign-key constraints:
   "cart_configurableproduct_product_id_fkey" FOREIGN KEY (product_id) 
REFERENCES cart_product(id) DEFERRABLE INITIALLY DEFERRED
   "cart_configurableproduct_variation_id_fkey" FOREIGN KEY 
(variation_id) REFERENCES cart_propertyvariation(id) DEFERRABLE 
INITIALLY DEFERRED






--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql


Re: [SQL] Counting days ...

2008-03-14 Thread Aarni Ruuhimäki
On Friday 14 March 2008 18:09, Frank Bax wrote:
> >
> > Is zero days/nights, ignored. Not even possible to insert in the
> > application. end_day must be greater than start_day.
>
> You should still consider rows that are "out of range" or "zero nights"
> in your test cases to make sure your report processes them correctly.

For the WHERE clause for Jan 08 (will be $date1 and $date2), getting there. 

1. start_day before period_start, end_day = period_start #1
2. start_day before period_start, end_day in period #1
3. start_day before period_start, end_day = period_end #1
4. start_day = period_start, end_day in period #2
5. start_day in period, end_day in period #3
6. start_day = period_start, end_day = period_end #2
7. start_day in period, end_day = period_end #3
8. start_day in period, end_day after period_end #3
9. start_day = period_start, end_day after period_end #2
10. start_day before period_start, end_day after period_end #1


SELECT res_id, to_char(res_start_day, 'DD.MM.'), to_char(res_end_day, 
'DD.MM.')
FROM product_res
WHERE 
group_id = 1 AND res_start_day < '2008-01-01' AND res_end_day >= '2008-01-01' 
# covers 1,2,3,10
OR
group_id = 1 AND res_start_day = '2008-01-01' AND res_end_day >= '2008-01-01' 
# covers 4,6,9
OR
group_id = 1 AND res_start_day >= '2008-01-01' AND res_start_day < 
'2008-01-31' AND res_end_day >= '2008-01-01'; # covers 5,7,8

(499 rows) not yet summing up or grouping by.

But is this getting too heavy ? I have three more (optional) parameters to 
pass into the query, which narrow down the result. All values are stored also 
in the product_res table.

1. Area/region ID from dropdown, populated by areas that have products
2. Company ID from dropdown, dynamically populated according to the optional 
area selection with companies that have products in the selected area
3. Product ID from dropdown, dynamically populated by the optional company 
selection with the selected company's products in the selected area

So the WHERE clause would go like:

group_id = 1 AND res_start_day < '$date1' AND res_end_day >= '$date1' [AND 
region_id = $region_id] [AND company_id = $company_id] [AND product_id = 
$product_id]
OR 
group_id = 1 AND res_start_day = '$date1' AND res_end_day >= '$date1' [AND 
region_id = $region_id] [AND company_id = $company_id] [AND product_id = 
$product_id]
OR
group_id = 1 AND res_start_day >= '$date1' AND res_start_day < '$date2' AND 
res_end_day >= '$date1' [AND region_id = $region_id] [AND company_id = 
$company_id] [AND product_id = $product_id]

Cheerio,

-- 
Aarni Ruuhimäki
---
Burglars usually come in through your windows.
---

-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql